// SCRIPT V 1.01 gsap.registerPlugin(ScrollTrigger, SplitText, AttrPlugin); // Global variable to hold SplitText instances and split state const splitTextData = { instances: [], // An array for storing SplitText instances elements: new Map() // Map to keep track of which elements are already broken }; // SMOOTH // Declare lenis globally let lenis; function Smooth() { // Destroy previous Lenis instance if it exists if (lenis) { lenis.destroy(); } // Initialize Lenis with your original settings lenis = new Lenis({ duration: 2, smoothTouch: false }); // Attach ScrollTrigger update lenis.on('scroll', ScrollTrigger.update); // Attach GSAP ticker for Lenis RAF gsap.ticker.add((time) => { lenis.raf(time * 1000); }); // Ensure lag smoothing is disabled gsap.ticker.lagSmoothing(0); // Lenis Start / Stop / Toggle Elements $('[data-lenis-start]').on('click', function () { lenis.start(); }); $('[data-lenis-stop]').on('click', function () { lenis.stop(); }); $('[data-lenis-toggle]').on('click', function () { $(this).toggleClass("stop-scroll"); if ($(this).hasClass("stop-scroll")) { lenis.stop(); } else { lenis.start(); } }); // Remove previous keydown event listeners to prevent duplication $(document).off('keydown.lenis'); // Handle keyboard scrolling with Arrow Up and Arrow Down $(document).on('keydown.lenis', function (event) { // Define the scroll step (in pixels) const scrollStep = 300; // You can adjust this value const currentScroll = lenis.actualScroll; // Current scroll position // Arrow Down if (event.key === 'ArrowDown') { event.preventDefault(); // Prevent default browser scrolling lenis.scrollTo(currentScroll + scrollStep, { duration: 1, // Smooth scroll duration easing: (t) => 1 - Math.pow(1 - t, 2.5) // Custom easing (cubic ease-out) }); } // Arrow Up if (event.key === 'ArrowUp') { event.preventDefault(); // Prevent default browser scrolling lenis.scrollTo(currentScroll - scrollStep, { duration: 1, // Smooth scroll duration easing: (t) => 1 - Math.pow(1 - t, 2.5) // Custom easing (cubic ease-out) }); } }); } // SMOOTH // Arrays to store timelines for each animation type let headingIntoViewTimelines = []; let textIntoViewTimelines = []; let simpleElementsTimelines = []; let buttonIntoViewTimelines = []; let separatorLineTimelines = []; let dropdownTimelines = []; let footerTimelines = []; let mediaTimelines = []; function IntoView() { // Media query handling with GSAP matchMedia const mm = gsap.matchMedia(); // HEADING INTO VIEW let headingIntoView = $('.text-block .heading').not( '.section.hero .heading, .section.footer .heading, .cta-block .heading, .menu-overlay-block .heading, .dropdown-block .heading' ); if (headingIntoView.length) { gsap.utils.toArray(headingIntoView).forEach(function (elem) { const innerSplit = new SplitText(elem, { type: 'lines', linesClass: 'text-line' }); // Set initial state (hide lines) gsap.set(innerSplit.lines, { y: '110%', opacity: 0, //willChange: 'transform, opacity' }); // Create paused timeline without auto-triggering const splitTimeline = gsap.timeline({ paused: true, onComplete: () => { innerSplit.revert(); } }); splitTimeline.to(innerSplit.lines, { duration: 1.1, y: 0, opacity: 1, ease: 'Power4.easeOut', stagger: 0.12 }); // Create ScrollTrigger to track visibility const scrollTrigger = ScrollTrigger.create({ trigger: elem, scrub: false, start: 'top 90%', end: 'bottom 0%', }); headingIntoViewTimelines.push({ timeline: splitTimeline, scrollTrigger: scrollTrigger, element: elem }); }); } // TEXT INTO VIEW let textIntoView = $('.text-block .text, .w-richtext p, .w-richtext li').not( '.text.w-richtext, .section.hero .text, .section.hero .text.w-richtext p, .section.footer .text, .cta-block .text, .button-block .text, .button-block .text, .form-wrapper .text, .menu-overlay-block .text, .dropdown-block .text' ); if (textIntoView.length) { gsap.utils.toArray(textIntoView).forEach(function (elem) { // Fixing empty rows manually elem.innerHTML = elem.innerHTML.replace(/

/g, "

"); const innerSplit = new SplitText(elem, { type: 'lines', linesClass: 'text-line' }); // Set initial state (hide lines and list items) gsap.set(innerSplit.lines, { y: '110%', opacity: 0, //willChange: 'transform, opacity' }); if (elem.tagName.toLowerCase() === 'li') { gsap.set(elem, { opacity: 0, //willChange: 'opacity' }); } // Create paused timeline const splitTimeline = gsap.timeline({ paused: true, onComplete: () => { innerSplit.revert(); // Deleting empty lines elem.querySelectorAll('.empty-line').forEach(line => line.remove()); } }); // Animate list items (only opacity) and lines (with lift) if (elem.tagName.toLowerCase() === 'li') { splitTimeline.to(elem, { duration: 1.1, opacity: 1, ease: 'Power4.easeOut' }, 0); // Start at the beginning } splitTimeline.to(innerSplit.lines, { duration: 1.1, y: 0, opacity: 1, ease: 'Power4.easeOut', stagger: 0.06 }, 0); // Sync with li animation // Create ScrollTrigger to track visibility const scrollTrigger = ScrollTrigger.create({ trigger: elem, scrub: false, start: 'top 90%', end: 'bottom 0%', }); textIntoViewTimelines.push({ timeline: splitTimeline, scrollTrigger: scrollTrigger, element: elem }); }); } // SIMPLE ELEMENTS FADE IN let simpleElements = $( '.vector.rating, .image, .video-block, .navbar-block, .button-block, .section.footer').not( '.dropdown-block .image, .navbar-block .button-block, .section.footer .button-block'); if (simpleElements.length) { gsap.utils.toArray(simpleElements).forEach(function (elem) { // Set initial state (hide elements) gsap.set(elem, { opacity: 0, //willChange: 'opacity' }); // Create paused timeline const fadeTimeline = gsap.timeline({ paused: true, /*onComplete: () => { gsap.set(elem, { willChange: 'auto' }); }*/ }); fadeTimeline.to(elem, { duration: 1.5, opacity: 1, ease: 'Power2.easeOut' }); // Create ScrollTrigger to track visibility const scrollTrigger = ScrollTrigger.create({ trigger: elem, scrub: false, start: 'top 90%', end: 'bottom 0%', onEnter: () => fadeTimeline.play() }); simpleElementsTimelines.push({ timeline: fadeTimeline, scrollTrigger: scrollTrigger, element: elem }); }); } // BUTTON INTO VIEW /*let buttonIntoView = $('.button-block').not( '.section.hero .button-block, .navbar-block .button-block, .cta-block .button-block, .section.footer .button-block, .back-to-top-wrapper .button-block' ); if (buttonIntoView.length) { gsap.utils.toArray(buttonIntoView).forEach((elem) => { const buttonText = elem.querySelector('.text'); const buttonLineContainer = elem.querySelector('.button-line-container'); const arrowMask = elem.querySelector('.arrow-mask'); let textLine = null; // Variable for text-line // Set initial state for elements if (buttonText) { // Create text-mask wrapper const textMask = document.createElement('div'); textMask.className = 'text-mask'; // Create text-line wrapper textLine = document.createElement('div'); textLine.className = 'text-line'; // Move buttonText content into textLine while (buttonText.firstChild) { textLine.appendChild(buttonText.firstChild); } // Add textLine to textMask, and textMask to buttonText textMask.appendChild(textLine); buttonText.appendChild(textMask); // Set initial state for textLine gsap.set(textLine, { y: '150%', //willChange: 'transform' }); } if (buttonLineContainer) { gsap.set(buttonLineContainer, { scaleX: 0, transformOrigin: 'left' }); } if (arrowMask) { gsap.set(arrowMask, { scale: 0, transformOrigin: '0% 100%' }); } // Create paused timeline const tl = gsap.timeline({ paused: true }); if (textLine) { tl.to(textLine, { duration: 0.8, y: 0, ease: 'Power4.easeOut', stagger: 0.12, }, 0); } if (buttonLineContainer) { tl.to(buttonLineContainer, { duration: 0.7, scaleX: 1, ease: 'Power3.easeOut', }, 0.15); } if (arrowMask) { tl.to(arrowMask, { duration: 0.7, scale: 1, ease: 'Power4.easeOut', }, 0.15); } // Create ScrollTrigger to track visibility const scrollTrigger = ScrollTrigger.create({ trigger: elem, scrub: false, start: 'top 90%', end: 'bottom 0%', }); buttonIntoViewTimelines.push({ timeline: tl, scrollTrigger: scrollTrigger, element: elem }); }); }*/ // FOOTER INTO VIEW /*let footerSection = $('.section.footer'); if (footerSection.length) { gsap.utils.toArray(footerSection).forEach(function (elem) { // Select all text elements to animate let footerText = $(elem).find('.text, .button-text .text, .text._14px'); let footerSocialIcons = $(elem).find('.vector.social'); let footerButtonBlocks = $(elem).find('.button-block'); // Split text into lines using SplitText let footerTextSpitted = false; function splitFooterText() { gsap.utils.toArray(footerText).forEach(function (textElem) { textElem.innerHTML = textElem.innerHTML.replace(/

/g, "

"); const innerSplit = new SplitText(textElem, { type: 'lines', linesClass: 'text-line' }); const outerSplit = new SplitText(textElem, { type: 'lines', linesClass: 'text-mask' }); gsap.set(innerSplit.lines, { y: '150%', //willChange: 'transform' }); gsap.set(outerSplit.lines, { overflow: 'hidden', display: 'block' }); }); footerTextSpitted = true; } // Initial setup for social icons and button lines gsap.set(footerSocialIcons, { opacity: 0, scale: 0.5 }); gsap.set(footerButtonBlocks.find('.button-line-container'), { scaleX: 0, transformOrigin: 'left' }); // Split text if not already done if (!footerTextSpitted) { splitFooterText(); } // Create paused timeline const tl = gsap.timeline({ paused: true }); tl.to($(elem).find('.text-line'), { duration: 0.8, y: 0, ease: 'Power4.easeOut', stagger: 0.1 }, 0) .to(footerButtonBlocks.find('.button-line-container'), { duration: 0.5, scaleX: 1, ease: 'Power3.easeOut', stagger: 0.1 }, 0.2) .to(footerSocialIcons, { duration: 0.5, opacity: 1, scale: 1, ease: 'Power2.easeOut', stagger: 0.05 }, 0.3); // Create ScrollTrigger to track visibility const scrollTrigger = ScrollTrigger.create({ trigger: elem, start: 'top 90%' }); footerTimelines.push({ timeline: tl, scrollTrigger: scrollTrigger, element: elem }); }); }*/ // SEPARATOR LINES INTO VIEW let separatorLine = $('.separator-line').not( '.section.hero .separator-line, .navbar-block .separator-line, .dropdown-block .separator-line' ); if (separatorLine.length) { gsap.utils.toArray(separatorLine).forEach(function (elem) { // Set initial state gsap.set(elem, { width: '0%' }); // Create paused timeline const tl = gsap.timeline({ paused: true }); tl.to(elem, { duration: 1.5, width: '100%', ease: 'power4' }); // Create ScrollTrigger to track visibility const scrollTrigger = ScrollTrigger.create({ trigger: elem, scrub: false, start: 'top 90%', end: 'bottom 0%', }); separatorLineTimelines.push({ timeline: tl, scrollTrigger: scrollTrigger, element: elem }); }); } // DROPDOWN INTO VIEW let dropdownBlocks = $('.dropdown-block'); // Check if dropdown blocks exist if (dropdownBlocks.length) { gsap.utils.toArray(dropdownBlocks).forEach(function (elem) { // Select heading, image, separator line, and plus lines within the dropdown block const heading = elem.querySelector('.heading'); const image = elem.querySelector('.image-block.dropdown img'); const separator = elem.querySelector('.separator-line.dropdown'); const plusLines = elem.querySelectorAll('.dropdown-plus-line .dropdown-plus-solid'); // Split heading into lines for animation let innerSplit = null; if (heading) { innerSplit = new SplitText(heading, { type: 'lines', linesClass: 'text-line' }); } // Set initial states for heading lines, image, separator line, and plus lines if (innerSplit) { gsap.set(innerSplit.lines, { y: '110%', opacity: 0, //willChange: 'transform, opacity' }); } if (image) { gsap.set(image, { opacity: 0, //willChange: 'opacity' }); } if (separator) { gsap.set(separator, { width: '0%', //willChange: 'width' }); } if (plusLines.length) { gsap.set(plusLines, { width: '0%', //willChange: 'width, height' }); } // Create a paused timeline for the animation const dropdownTimeline = gsap.timeline({ paused: true, onComplete: () => { if (innerSplit) innerSplit.revert(); // Revert SplitText only if it was created /*gsap.set(image, { willChange: 'auto' }); gsap.set(separator, { willChange: 'auto' }); gsap.set(plusLines, { willChange: 'auto' });*/ } }); // Animate heading lines with lift and fade-in if (innerSplit) { dropdownTimeline.to(innerSplit.lines, { duration: 1.1, y: 0, opacity: 1, ease: 'Power4.easeOut', stagger: 0.12 }); } // Animate plus lines with a delay of 0.2 seconds if (plusLines.length) { dropdownTimeline.to(plusLines, { duration: 0.5, width: '100%', // Expand horizontal line ease: 'Power4.easeOut', stagger: 0.2 }, 0.2); } // Animate separator line with a delay of 0.3 seconds if (separator) { dropdownTimeline.to(separator, { duration: 1.5, width: '100%', ease: 'Power4.easeOut' }, 0.3); } // Animate image if it exists, with a delay of 0.3 seconds if (image) { dropdownTimeline.to(image, { duration: 1.5, opacity: 1, ease: 'Power2.easeOut' }, 0.3); } // Create ScrollTrigger to start animation when element enters viewport const scrollTrigger = ScrollTrigger.create({ trigger: elem, scrub: false, start: 'top 90%', end: 'bottom 0%', onEnter: () => dropdownTimeline.play() }); // Add timeline to array for later initialization dropdownTimelines.push({ timeline: dropdownTimeline, scrollTrigger: scrollTrigger, element: elem }); }); } // MEDIA BLOCKS INTO VIEW /*const mediaBlocks = $('.image-block .image, .video-block').not('.dropdown-block .image'); // Create or find