gsap.registerPlugin(ScrollTrigger); // LOADER /* gsap.to(".loader-logo", { rotationZ: 360, duration: 10, repeat: 30, ease: "none" }); */ // variables let customEase = "M0,0,C0,0,0.13,0.34,0.238,0.442,0.305,0.506,0.322,0.514,0.396,0.54,0.478,0.568,0.468,0.56,0.522,0.584,0.572,0.606,0.61,0.719,0.714,0.826,0.798,0.912,1,1,1,1"; let counter = { value: 0 }; let loaderDuration = 10; // If not a first time visit in this tab if (sessionStorage.getItem("visited") !== null) { loaderDuration = 2; counter = { value: 75 }; } sessionStorage.setItem("visited", "true"); function updateLoaderText() { let progress = Math.round(counter.value); $(".loader_number").text(progress); } function endLoaderAnimation() { $(".trigger").click(); } let tl = gsap.timeline({ onComplete: endLoaderAnimation }); tl.to(counter, { value: 100, onUpdate: updateLoaderText, duration: loaderDuration, ease: CustomEase.create("custom", customEase) }); tl.to( ".loader_progress", { height: "100%", duration: loaderDuration, ease: CustomEase.create("custom", customEase) }, 0 ); tl.fromTo( ".loader", { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)" }, { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", ease: CustomEase.create("custom", customEase) } ); tl.to(".loader", { display: "none" }); tl.to("body", { overflow: "visible", ease: "none" }); /** ** START ANIMATIONs ONLY IF ITEM IS INVIEW ======================================================================================================================= ** **/ // START KEYFRAMES $("[is-inview]").on("inview", function (event, isInView) { if (isInView) { $(this).addClass("init-kf"); } else { $(this).removeClass("init-kf"); } }); // START KEYFRAMES $("[is-inview]").on("inview", function (event, isInView) { if (isInView) { $(this).addClass("init-kf"); } else { $(this).removeClass("init-kf"); } }); // START GSAP ANIMS // MARQUEE POWER-UP window.addEventListener("DOMContentLoaded", (event) => { // attribute value checker function attr(defaultVal, attrVal) { const defaultValType = typeof defaultVal; if (typeof attrVal !== "string" || attrVal.trim() === "") return defaultVal; if (attrVal === "true" && defaultValType === "boolean") return true; if (attrVal === "false" && defaultValType === "boolean") return false; if (isNaN(attrVal) && defaultValType === "string") return attrVal; if (!isNaN(attrVal) && defaultValType === "number") return +attrVal; return defaultVal; } // marquee component $("[tr-marquee-element='component']").each(function (index) { let componentEl = $(this), panelEl = componentEl.find("[tr-marquee-element='panel']"), triggerHoverEl = componentEl.find("[tr-marquee-element='triggerhover']"), triggerClickEl = componentEl.find("[tr-marquee-element='triggerclick']"); let speedSetting = attr(100, componentEl.attr("tr-marquee-speed")), verticalSetting = attr(false, componentEl.attr("tr-marquee-vertical")), reverseSetting = attr(false, componentEl.attr("tr-marquee-reverse")), scrollDirectionSetting = attr( false, componentEl.attr("tr-marquee-scrolldirection") ), scrollScrubSetting = attr( false, componentEl.attr("tr-marquee-scrollscrub") ), moveDistanceSetting = -100, timeScaleSetting = 0.55, pausedStateSetting = false; if (reverseSetting) moveDistanceSetting = 100; let marqueeTimeline = gsap.timeline({ repeat: -1, onReverseComplete: () => marqueeTimeline.progress(1) }); if (verticalSetting) { speedSetting = panelEl.first().height() / speedSetting; marqueeTimeline.fromTo( panelEl, { yPercent: 0 }, { yPercent: moveDistanceSetting, ease: "none", duration: speedSetting } ); } else { speedSetting = panelEl.first().width() / speedSetting; marqueeTimeline.fromTo( panelEl, { xPercent: 0 }, { xPercent: moveDistanceSetting, ease: "none", duration: speedSetting } ); } let scrubObject = { value: 1 }; ScrollTrigger.create({ trigger: "body", start: "top top", end: "bottom bottom", onUpdate: (self) => { if (!pausedStateSetting) { if (scrollDirectionSetting && timeScaleSetting !== self.direction) { timeScaleSetting = self.direction; marqueeTimeline.timeScale(self.direction); } if (scrollScrubSetting) { let v = self.getVelocity() * 0.006; v = gsap.utils.clamp(-60, 60, v); let scrubTimeline = gsap.timeline({ onUpdate: () => marqueeTimeline.timeScale(scrubObject.value) }); scrubTimeline.fromTo( scrubObject, { value: v }, { value: timeScaleSetting, duration: 0.5 } ); } } } }); function pauseMarquee(isPausing) { pausedStateSetting = isPausing; let pauseObject = { value: 1 }; let pauseTimeline = gsap.timeline({ onUpdate: () => marqueeTimeline.timeScale(pauseObject.value) }); if (isPausing) { pauseTimeline.fromTo( pauseObject, { value: timeScaleSetting }, { value: 0, duration: 0.5 } ); triggerClickEl.addClass("is-paused"); } else { pauseTimeline.fromTo( pauseObject, { value: 0 }, { value: timeScaleSetting, duration: 0.5 } ); triggerClickEl.removeClass("is-paused"); } } if (window.matchMedia("(pointer: fine)").matches) { triggerHoverEl.on("mouseenter", () => pauseMarquee(true)); triggerHoverEl.on("mouseleave", () => pauseMarquee(false)); } triggerClickEl.on("click", function () { !$(this).hasClass("is-paused") ? pauseMarquee(true) : pauseMarquee(false); }); }); }); // CTA <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< let typeSplit = new SplitType(".is--stagger", { types: "words, chars", tagName: "span" }); $(".heading-wrap").each(function (index) { let headings = $(this).find(".is--stagger"); let tl = gsap.timeline({ repeat: -1 }); tl.set($(this), { opacity: 1 }); headings.each(function (index) { if (index > 0) { tl.from( $(this).find(".char"), { yPercent: 100, stagger: { amount: 0.4 }, duration: 0.4 }, "<0.1" ); } if (index < headings.length - 1) { tl.to($(this).find(".char"), { delay: 1, yPercent: -100, stagger: { amount: 0.4 }, duration: 0.4 }); } }); }); const swiper1 = new Swiper(".mobile-swiper", { // Optional parameters direction: "horizontal", loop: false, slidesPerView: "auto", slidesPerGroup: 1, spaceBetween: 16, centeredSlides: false, speed: 300, // Responsive breakpoints breakpoints: { // when window width is >= 480px 480: { slidesPerView: 1 }, // when window width is >= 768px 768: { slidesPerView: 2 }, // when window width is >= 992px 992: { slidesPerView: 3 } }, // Navigation arrows navigation: { nextEl: ".button-next", prevEl: ".button-prev" } // And if we need scrollbar /* scrollbar: { el: ".swiper-scrollbar", draggable: true } */ }); /* $(".price-swiper").append( `
Prev
Next
` ); */ const swiper2 = new Swiper(".price-swiper", { // Optional parameters direction: "horizontal", slidesPerView: 1, grabCurosor: true, loop: true, centeredSlides: false, autoplay: { delay: 2500, disableOnInteraction: true }, navigation: { nextEl: "[price-prev]", prevEl: "[price-next]" }, speed: 500, breakpoints: { 480: { slidesPerView: 1 }, 768: { slidesPerView: 1 }, 992: { slidesPerView: "auto" } } }); const swiper3 = new Swiper(".proc-swiper", { // Optional parameters direction: "horizontal", loop: false, slidesPerView: 1, slidesPerGroup: 1, spaceBetween: 16, centeredSlides: false, speed: 300, // Responsive breakpoints breakpoints: { // when window width is >= 480px 480: { slidesPerView: 1, slidesPerGroup: 1 }, // when window width is >= 768px 768: { slidesPerView: 1, slidesPerGroup: 1 }, // when window width is >= 992px 992: { slidesPerView: 2 } }, // And if we need scrollbar scrollbar: { el: $(".swiper-drag-wrapper")[0], draggable: true, dragClass: "swiper-drag", snapOnRelease: true } }); const swiper4 = new Swiper(".compare-swiper", { // Optional parameters direction: "horizontal", slidesPerView: 1, grabCurosor: true, loop: true, centeredSlides: false, navigation: { nextEl: ".compare-slide-wrapper .button-next", prevEl: ".compare-slide-wrapper .button-prev" }, speed: 300, breakpoints: { 480: { slidesPerView: 1 }, 768: { slidesPerView: 1 }, 992: { slidesPerView: "auto" } } }); const swiper5 = new Swiper(".testi-swiper", { // Optional parameters direction: "horizontal", slidesPerView: 1, spaceBetween: 16, loop: false, grabCurosor: true, centeredSlides: false, navigation: { nextEl: ".testi-nav .button-next2", prevEl: ".testi-nav .button-prev2" }, speed: 300, breakpoints: { 480: { slidesPerView: "auto" }, 768: { slidesPerView: "auto" }, 992: { slidesPerView: 2 } } }); $("[case-mobile-trigger]").on("click", function () { $(this).siblings(".mobile-case-body").fadeToggle(400); }); $(".case-plus.is--mobile").on("click", function () { $(this).toggleClass("m-plus-closed"); }); // SCROLL ANIMATIONS ======================================================================================================= // texts window.addEventListener("DOMContentLoaded", (event) => { // Split text into spans let typeSplit = new SplitType("[text-split]", { types: "words", tagName: "span" }); // Link timelines to scroll position function createScrollTrigger(triggerElement, timeline) { // Reset tl when scroll out of view past bottom of screen /* ScrollTrigger.create({ trigger: triggerElement, start: "top bottom", onLeaveBack: () => { timeline.progress(0); timeline.pause(); } }); */ // Play tl when scrolled into view (60% from top of screen) ScrollTrigger.create({ trigger: triggerElement, start: "top 90%", onEnter: () => timeline.play() }); } $("[words-slide-up]").each(function (index) { let tl = gsap.timeline({ paused: true }); tl.from($(this).find(".word"), { opacity: 0, yPercent: 100, duration: 0.7, stagger: 0.03, //delay: 0.05, ease: "expo.out" }); createScrollTrigger($(this), tl); }); // Avoid flash of unstyled content gsap.set("[text-split]", { opacity: 1 }); }); function itemStagger() { const allWrappers = [...document.querySelectorAll("[item-wrapper]")]; allWrappers.forEach((item, i) => { let tl = gsap.timeline({ scrollTrigger: { trigger: item, start: "top bottom", end: "bottom top" //toggleActions: "restart restart restart reverse" } }); tl.from(item.children, { yPercent: 100, opacity: 0, stagger: { each: 0.15 }, duration: 0.3, delay: 0.5, easing: "Sine.easeOut" }); }); } itemStagger();