1/** 2 * Text Overlay GSAP Widget - Animation Script 3 * Uses GSAP ScrollTrigger for scroll-based animations 4 */ 5 6(function () { 7 'use strict'; 8 9 // Store ScrollTrigger instances for cleanup 10 let scrollTriggerInstances = []; 11 12 // Initialize when DOM is ready 13 function init() { 14 // Register ScrollTrigger 15 if (typeof gsap !== 'undefined' && typeof ScrollTrigger !== 'undefined') { 16 gsap.registerPlugin(ScrollTrigger); 17 } else { 18 console.warn('GSAP or ScrollTrigger not loaded for Text Overlay widget'); 19 return; 20 } 21 22 // Kill existing ScrollTriggers to prevent duplicates 23 scrollTriggerInstances.forEach(st => st.kill()); 24 scrollTriggerInstances = []; 25 26 // Find all Text Overlay widgets 27 const widgets = document.querySelectorAll('.wml-text-overlay-gsap'); 28 29 widgets.forEach(function (widget) { 30 initWidget(widget); 31 }); 32 } 33 34 function initWidget(widget) { 35 const containerId = widget.id; 36 37 // Get animation settings from data attributes 38 const overlayScale = parseFloat(widget.dataset.overlayScale) || 90; 39 const overlayDuration = parseFloat(widget.dataset.overlayDuration) || 2; 40 const overlayEase = widget.dataset.overlayEase || 'power2.in'; 41 const scrollOverlay = widget.dataset.scrollOverlay || '2000px'; 42 43 // Get elements 44 const overlay = widget.querySelector('.wml-tog-overlay'); 45 const svg = widget.querySelector('.wml-tog-svg'); 46 47 if (!overlay) { 48 return; 49 } 50 51 // Parse scroll distances 52 const overlayScrollDist = parseInt(scrollOverlay) || 2000; 53 54 // Reset all elements to initial state 55 gsap.set(overlay, { 56 transformOrigin: 'center center', 57 scale: 1, 58 opacity: 1, 59 visibility: 'visible' 60 }); 61 62 // Main overlay animation with pinning 63 // Main overlay animation with pinning - Using Timeline for proper easing support 64 const tl = gsap.timeline({ 65 scrollTrigger: { 66 trigger: widget, 67 start: 'top top', 68 end: '+=' + overlayScrollDist, 69 pin: true, 70 pinSpacing: true, 71 scrub: 0.5, 72 } 73 }); 74 75 tl.to(overlay, { 76 scale: overlayScale, 77 opacity: 0, 78 ease: overlayEase 79 }); 80 81 if (tl.scrollTrigger) { 82 scrollTriggerInstances.push(tl.scrollTrigger); 83 } 84 85 // Responsive SVG sizing 86 function resizeSvg() { 87 if (!svg) return; 88 89 const ratio = 0.5625; // 16:9 aspect ratio 90 const w = window.innerWidth; 91 const h = window.innerHeight; 92 93 if (w > h * (16 / 9)) { 94 gsap.set(svg, { attr: { width: w, height: w * ratio } }); 95 } else { 96 gsap.set(svg, { attr: { width: h / ratio, height: h } }); 97 } 98 } 99 100 resizeSvg(); 101 window.addEventListener('resize', resizeSvg); 102 } 103 104 // Initialize on DOMContentLoaded 105 if (document.readyState === 'loading') { 106 document.addEventListener('DOMContentLoaded', init); 107 } else { 108 init(); 109 } 110 111 // Re-initialize for Bricks Builder preview 112 document.addEventListener('bricks/ajax/load_page', init); 113 114 // Also handle dynamic content loading 115 if (typeof jQuery !== 'undefined') { 116 jQuery(document).on('bricks/builder/inserted', function () { 117 setTimeout(init, 100); 118 }); 119 } 120})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.