// Initialize Lenis const lenis = new Lenis({ duration: 1.2, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), smooth: true, }); function raf(time) { lenis.raf(time); requestAnimationFrame(raf); } requestAnimationFrame(raf); // Sync Lenis with GSAP ScrollTrigger lenis.on("scroll", ScrollTrigger.update); const tlHeroabout = gsap.timeline(); // 1. Fades in the element with the class .main-logo from opacity 0 tlHeroabout.fromTo(".section-hero", { opacity: 0 }, { opacity: 1, duration: 2, ease: "none" } ); // 2. Fades in the element with the class .video-bg-wrap-hero from opacity 0 tlHeroabout.to(".video-bg-wrap-hero-about", { opacity: 1, duration: 3, ease: "power1.in" }, 0 ); const tlHeromain = gsap.timeline(); tlHeromain.to(".video-bg-wrap-hero", { opacity: 1, duration: 3, ease: "power1.in" } ); document.addEventListener('DOMContentLoaded', function() { /************************************************** * Start Initialization code for the slider without autoplay ***********************************************************/ $('.step-slider-here').slick({ autoplay: false, // Autoplay is initially disabled autoplaySpeed: 3000, speed: 600, centerMode: true, variableWidth: true, infinite: true, dots: false, arrows: true, // Enable arrows prevArrow: '.prev-arrow', // Specify class for the "previous" arrow nextArrow: '.next-arrow', // Specify class for the "next" arrow draggable: true, }); // Function to enable autoplay function enableAutoplay() { $('.step-slider-here').slick('slickSetOption', 'autoplay', true, true); } // ScrollTrigger setup ScrollTrigger.create({ trigger: '.step-slider-here', // The trigger is your slider start: 'top 75%', // When the top of the slider reaches 75% of the top of the window onEnter: () => enableAutoplay(), // Enable autoplay on enter }); /* Animation for changing Y-axis position on scroll for elements with the attribute [data-anime-position] */ document.querySelectorAll("[data-anime-position]").forEach((animeElement) => { const endY = animeElement.getAttribute("data-end-y") || "-60%"; gsap.to(animeElement, { y: endY, ease: "none", scrollTrigger: { trigger: animeElement, start: "top 60%", end: "bottom top", scrub: true, }, }); }); /********************************************************** * End Initialization code for the slider without autoplay ***********************************************************/ /************************************* * Start code Animation for elements with the attribute [headline-anime] *************************************/ document.querySelectorAll("[headline-anime]").forEach((headlineElement) => { const headlineChars = new SplitType(headlineElement, { types: ["words", "lines"], }); headlineChars.words.forEach((word, index) => { gsap.set(word, { opacity: 0, y: `${200 + index * 20}%` }); }); headlineChars.words.forEach((word) => { gsap.to(word, { scrollTrigger: { trigger: headlineElement, start: "top 80%", end: "bottom 20%", scrub: true, toggleActions: "play none none none", }, opacity: 1, y: "0%", duration: 1, ease: "power2.out" }); }); }); /************************************* * End code Animation for elements with the attribute [headline-anime] *************************************/ /********************************* * Start code animation for wrappers with the attribute [anime-block-wrap] *********************************/ document.querySelectorAll("[anime-block-wrap]").forEach((wrapElement) => { const headlineElementInWrap = wrapElement.querySelector("[headline-anime-in-wrap]"); const textLinesElementsInWrap = wrapElement.querySelectorAll("[text-lines-anime]"); const opacityElementInWrap = wrapElement.querySelector("[anime-opacity]"); if (headlineElementInWrap) { const headlineCharsInWrap = new SplitType(headlineElementInWrap, { types: ["words", "lines"], }); headlineCharsInWrap.words.forEach((word, index) => { gsap.set(word, { opacity: 0, y: 200 + index * 20 }); }); headlineCharsInWrap.words.forEach((word) => { gsap.to(word, { scrollTrigger: { trigger: wrapElement, start: "top 80%", end: "bottom 20%", scrub: true, toggleActions: "play none none none", }, opacity: 1, y: 0, duration: 1, ease: "power2.out" }); }); } const headlineHeight = headlineElementInWrap ? headlineElementInWrap.offsetHeight : 0; if (textLinesElementsInWrap.length > 0) { textLinesElementsInWrap.forEach((lineElement, lineIndex) => { const lineCharsInWrap = new SplitType(lineElement, { types: ["lines"] }); lineCharsInWrap.lines.forEach((line, index) => { gsap.set(line, { opacity: 0, y: 300 + headlineHeight + index * 30 }); gsap.to(line, { scrollTrigger: { trigger: wrapElement, start: "top 80%", end: "bottom 20%", scrub: true, toggleActions: "play none none none", }, opacity: 1, y: 0, duration: 1, ease: "power2.out", delay: lineIndex * 0.1 }); }); }); if (opacityElementInWrap) { gsap.set(opacityElementInWrap, { opacity: 0, y: 500 }); gsap.to(opacityElementInWrap, { scrollTrigger: { trigger: wrapElement, start: "top 80%", end: "bottom 20%", scrub: true, toggleActions: "play none none none", }, opacity: 1, y: 0, duration: 0.3, ease: "power2.out", delay: 1.5 }); } } }); /********************************* * End code animation for wrappers with the attribute [anime-block-wrap] *********************************/ /********************************* * Start code Paralax animation *********************************/ document.querySelectorAll("[anime-paralax]").forEach((parallaxElement) => { const startY = parallaxElement.getAttribute("data-parallax-start") || "5rem"; // Determine end point depending on screen width let endY; if (window.innerWidth < 767) { endY = parallaxElement.getAttribute("data-parallax-end-mobile") || "-2rem"; // Set end point for mobile devices } else { endY = parallaxElement.getAttribute("data-parallax-end") || "0rem"; // Set standard end point } // Set initial parameters gsap.set(parallaxElement, { y: startY, opacity: 0 }); // Y-axis shift animation gsap.to(parallaxElement, { y: endY, ease: "none", scrollTrigger: { trigger: parallaxElement, start: "top bottom", end: "top 0%", scrub: true, }, }); // Opacity change animation gsap.to(parallaxElement, { opacity: 1, ease: "none", scrollTrigger: { trigger: parallaxElement, start: "top 90%", end: "top 60%", scrub: true, }, }); }); /********************************* * End code Paralax animation *********************************/ /******************************************************* * Start code Opacity animation for elements with the attribute [only-anime-opacity] *******************************************************/ document.querySelectorAll("[data-anime-opacity]").forEach((opacityElement) => { const startValue = opacityElement.getAttribute("data-opacity-start") || "top 80%"; const endValue = opacityElement.getAttribute("data-opacity-end") || "top 30%"; gsap.set(opacityElement, { opacity: 0 }); gsap.to(opacityElement, { opacity: 1, ease: "none", scrollTrigger: { trigger: opacityElement, start: startValue, end: endValue, scrub: true, }, }); }); /********************************* * End code Opacity animation *********************************/ /******************************************************* * Start code Animation for hiding/showing navbar * Use atribute [hide-navbar-triger] for any element on the page as trigger for begining animation *******************************************************/ const navbar = document.querySelector(".navbar"); document.querySelectorAll("[hide-navbar-triger]").forEach((triggerElement) => { gsap.to(navbar, { opacity: 0, y: "100%", duration: 1, ease: "power2.out", scrollTrigger: { trigger: triggerElement, start: "bottom 90%", end: "bottom 90%", toggleActions: "play none none reverse", scrub: false, }, }); }); /******************************************************* * End code Animation for hiding/showing navbar *******************************************************/ /******************************************************* * Start code for animate logo width after start scroll * Use atribute [logo-part-trigger] for any element on the page as trigger for begining animation *******************************************************/ if (window.innerWidth > 360) { const logoPart = document.querySelector(".logo-part"); document.querySelectorAll("[logo-part-trigger]").forEach((triggerElement) => { gsap.to(logoPart, { width: "4rem", duration: 0.8, ease: "power1.out", scrollTrigger: { trigger: triggerElement, start: "bottom 75%", toggleActions: "play none none reverse", scrub: false, }, }); }); } /******************************************************* * End code for animate logo width after start scroll *******************************************************/ /* Refresh ScrollTrigger after loading all elements */ ScrollTrigger.refresh(); }); /****************************************** * Start code Reveal text from opacity code ******************************************/ const splitTypes = document.querySelectorAll('.reveal-type'); splitTypes.forEach((char, i) => { const text = new SplitType(char, { types: ['chars', 'words'] }); gsap.from(text.chars, { scrollTrigger: { trigger: char, start: 'top 60%', end: 'bottom 60%', scrub: true, markers: false }, opacity: 0.2, stagger: 0.05, }) }); /**************************************** * End code Reveal text from opacity code ***************************************/ /********************************* * Start Popup login code *********************************/ document.addEventListener('DOMContentLoaded', function() { // Function to open the popup function openPopup() { const popup = document.querySelector('.popup-login'); if (popup) { popup.style.display = 'flex'; // Change display to flex setTimeout(() => { popup.style.opacity = '1'; // Animation to change opacity }, 10); // Small delay for applying display } } // Function to close the popup function closePopup() { const popup = document.querySelector('.popup-login'); if (popup) { popup.style.opacity = '0'; // Animation to change opacity setTimeout(() => { popup.style.display = 'none'; // Change display to none after the animation is complete }, 500); // Delay should match the duration of the animation } } // Add event listener for opening the popup document.querySelectorAll('[data-popup="login"]').forEach(function(link) { link.addEventListener('click', function(event) { event.preventDefault(); // Prevent link from navigating openPopup(); // Open popup }); }); // Add event listener for closing the popup on all elements with the class .close-popup document.querySelectorAll('.close-popup').forEach(function(closeButton) { closeButton.addEventListener('click', function() { closePopup(); // Close popup }); }); }); /********************************* * End of sequence code *********************************/ /********************************* * Start of sequence code *********************************/ gsap.registerPlugin(ScrollTrigger); const canvas = document.getElementById("sequenceCanvas"); if (canvas) { const context = canvas.getContext("2d"); // Array with image links const imageLinks = []; // Generate frames from 00006 to 00059 for (let i = 6; i <= 59; i++) { const frameNumber = i.toString().padStart(5, "0"); imageLinks.push( `https://klad.b-cdn.net/shareio/lottie/F3_seq_${frameNumber}.avif` ); } const frameCount = imageLinks.length; const images = []; const imageSequence = { frame: 0 }; let loadedImages = 0; // Load all images imageLinks.forEach((link) => { const img = new Image(); img.onload = () => { loadedImages++; if (loadedImages === frameCount) { initCanvas(); } }; img.src = link; images.push(img); }); function initCanvas() { resizeCanvas(); window.addEventListener("resize", resizeCanvas); gsap.timeline({ onUpdate: render, scrollTrigger: { trigger: ".image-sequence-section", pin: true, scrub: 1, end: "+=100%" // markers: true } }) .to(imageSequence, { frame: frameCount - 1, snap: "frame", ease: "none", duration: 1 }); animateText(); } function animateText() { const textElement = document.querySelector(".animesqtext"); if (!textElement) return; const textChars = new SplitType(textElement, { types: ["words", "lines"] }); textChars.words.forEach((word, index) => { gsap.set(word, { opacity: 0, y: `${300 + index * 50}%` }); }); textChars.words.forEach((word) => { gsap.to(word, { scrollTrigger: { trigger: textElement, start: "top 0%", scrub: 3 }, opacity: 1, y: "0%", duration: 2, ease: "power2.out" }); }); } function render() { if (!images[imageSequence.frame]) return; context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage( images[imageSequence.frame], 0, 0, canvas.width, canvas.height ); } function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; render(); } } /********************************* * End of sequence code *********************************/ /********************************* * Start of new drum code *********************************/ // Animation for text lines and background elements document.querySelectorAll('.text-line-scroll').forEach((textLine) => { // Select elements with the class .anime-bg-el inside each text block const bgElement = textLine.querySelector('.anime-bg-el'); // Main animation for text lines and background element gsap.fromTo( textLine, { opacity: 0.2 }, // Initial opacity value for text line { opacity: 1, // Opacity value in the center of the screen scrollTrigger: { trigger: textLine, // Element tracking the scrolling start: 'center 70%', // Animation start end: 'center 30%', // Animation end scrub: true, // Smooth transition with scrolling onEnter: () => { textLine.style.opacity = 1; // Text line visible on enter if (bgElement) bgElement.style.opacity = 1; // Background also visible on enter }, onLeave: () => { textLine.style.opacity = 0.2; // Text line disappears on leave if (bgElement) bgElement.style.opacity = 0; // Background also disappears }, onEnterBack: () => { textLine.style.opacity = 1; // Text line visible on re-entry if (bgElement) bgElement.style.opacity = 1; // Background also visible on re-entry }, onLeaveBack: () => { textLine.style.opacity = 0.2; // Text line disappears on leaving back if (bgElement) bgElement.style.opacity = 0; // Background also disappears }, }, } ); }); /********************************* * End of new drum code *********************************/ /********************************* * Start Quasar eclipse *********************************/ gsap.to(".image-sequence", { opacity: 0, scrollTrigger: { trigger: ".features-block", start: "top 45%", end: "top 20%", // Можна налаштувати кінець анімації scrub: true } }); /********************************* * End Quasar eclipse *********************************/