CustomEase.create( "loaderEase", "M0,0,C0,0,0.10,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" ); CustomEase.create("ease-1", "M0,0 C0.15,0 0.15,1 1,1"); CustomEase.create( "ease-2", "M0,0 C0.071,0.505 0.192,0.726 0.318,0.852 0.45,0.984 0.504,1 1,1" ); CustomEase.create("ease-3", "0.65, 0.01, 0.05, 0.99"); const lenis = new Lenis({ syncTouch: true, syncTouchLerp: 0.075, touchInertiaExponent: 1.7, touchMultiplier: 1, }); gsap.ticker.add((time) => { lenis.raf(time * 1000); }); lenis.on("scroll", ScrollTrigger.update); let winW = window.innerWidth; window.addEventListener("resize", () => { if (window.innerWidth !== winW) { winW = window.innerWidth; ScrollTrigger.refresh(); } }); const onDesktop = (fn) => gsap.matchMedia().add("(min-width: 992px)", fn); const onTablet = (fn) => gsap.matchMedia().add("(max-width: 991px)", fn); onDesktop(() => {}); onTablet(() => {}); onDesktop(() => { document.fonts.ready.then(() => { document.querySelectorAll(".line-reveal-1").forEach((block) => { let split = SplitText.create(block, { type: "lines", linesClass: "line", autoSplit: true, }); gsap.fromTo( split.lines, { yPercent: 100, clipPath: "polygon(-10% -10%, 100% -10%, 100% -10%, -10% -10%)", }, { yPercent: 0, clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", stagger: { amount: 0.3 }, duration: 1.5, ease: "expo.out", scrollTrigger: { trigger: block, start: "top 85%", end: "clamp(bottom 20%)", toggleActions: "play none none none", }, } ); }); }); ScrollTrigger.refresh(); //scroll Text document.fonts.ready.then(() => { let split = SplitText.create(".charsplit", { type: "chars", charsClass: "char", smartWrap: true, }); console.log("text split"); document.querySelectorAll(".char-reveal-1").forEach((section) => { const chars = section.querySelectorAll(".char"); gsap.fromTo( chars, { yPercent: -100, clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { scrollTrigger: { trigger: section, start: "clamp(top 80%)", end: "clamp(bottom 20%)", toggleActions: "play none none none", }, yPercent: 0, clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", stagger: { amount: 0.8, }, duration: 1.5, ease: "expo.out", } ); }); }); // loop each reveal wrapper document.fonts.ready.then(() => { document.querySelectorAll(".char-reveal-load").forEach((section) => { const loadChars = section.querySelectorAll(".char"); gsap.fromTo( loadChars, { yPercent: -100, clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { scrollTrigger: { trigger: section, start: "top 95%", end: "bottom 80%", toggleActions: "play none none none", }, yPercent: 0, clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", stagger: { amount: 0.8, }, duration: 1.5, ease: "expo.out", } ); }); }); }); // ScrollTrigger.create({ // trigger: ".nav_trigger", // start: "bottom top", // onEnter: () => // gsap.to("[mr-nav]", { // backgroundColor: "#f6f6f4", // color: "#000", // duration: 0.3, // }), // onLeaveBack: () => // gsap.to("[mr-nav]", { // backgroundColor: "transparent", // color: "currentColor", // duration: 0.3, // }), // }); let lastScroll = window.scrollY; let direction = "none"; gsap.ticker.add(() => { const currentScroll = window.scrollY; if (currentScroll > lastScroll && direction !== "down") { direction = "down"; gsap.to(".nav_section", { yPercent: -100, duration: 0.8, ease: "ease-3", }); } else if (currentScroll < lastScroll && direction !== "up") { direction = "up"; gsap.to(".nav_section", { yPercent: 0, duration: 0.8, ease: "ease-3", }); } lastScroll = currentScroll; }); $("html, body").scrollTop(0); // marquee component 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; } $("[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 = 1, 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); }); }); onTablet(() => { function initMenu() { let navWrap = document.querySelector(".nav_section"); let state = navWrap.getAttribute("data-nav"); let menu = navWrap.querySelector(".menu"); let navInner = navWrap.querySelector(".nav_inner"); let menuToggles = document.querySelectorAll(".menu-btn"); let menuLinks = navWrap.querySelectorAll(".menu_link_flex"); let menuLine = navWrap.querySelectorAll(".menu_line"); let menuHam1 = navWrap.querySelectorAll(".menu-line.is-1"); let menuHam2 = navWrap.querySelectorAll(".menu-line.is-2"); let menuHam3 = navWrap.querySelectorAll(".menu-line.is-3"); let tl = gsap.timeline({}); const openNav = () => { lenis.stop(); navWrap.setAttribute("data-nav", "open"); tl.clear() .set(menu, { display: "flex", clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", }) .set(menuLine, { width: "0%", }) .to(navInner, { color: "#FFF", ease: "expo" }, "<") .fromTo( menu, { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)" }, { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", duration: 0.8, ease: "ease-3", }, "<15%" ) .fromTo( menuLine, { width: "0%" }, { width: "100%", duration: 0.8, stagger: 0.3, ease: "expo.out", }, "<19%" ) .fromTo( menuHam2, { width: "100%" }, { width: "0%", duration: 0.5, }, "<" ) .fromTo( menuHam1, { rotateZ: 0, y: 0, backgroundColor: "#12120D" }, { rotateZ: 45, y: "0.36rem", backgroundColor: "#FFF", duration: 0.5, }, "<" ) .fromTo( menuHam3, { rotateZ: 0, y: 0, backgroundColor: "#12120D" }, { rotateZ: -45, y: "-0.36rem", backgroundColor: "#FFF", duration: 0.5, }, "<" ) .fromTo( menuLinks, { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", yPercent: 100, }, { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", yPercent: 0, duration: 0.8, stagger: 0.2, ease: "expo.out", }, "<" ); }; const closeNav = () => { lenis.start(); navWrap.setAttribute("data-nav", "closed"); tl.clear() .to(menu, { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", duration: 0.4, ease: "ease-1", }) .to( menuHam2, { width: "100%", duration: 0.5, }, "<" ) .to( menuHam1, { rotateZ: 0, y: "0rem", backgroundColor: "#12120D", duration: 0.5, }, "<" ) .to( menuHam3, { rotateZ: 0, y: "0rem", backgroundColor: "#12120D", duration: 0.5, }, "<" ) .to(navInner, { color: "#12120D", ease: "expo" }, "<") .set(menu, { display: "none" }); }; // Toggle menu open / close depending on its current state menuToggles.forEach((toggle) => { toggle.addEventListener("click", () => { state = navWrap.getAttribute("data-nav"); if (state === "open") { closeNav(); } else { openNav(); } }); }); // If menu is open, you can close it using the "escape" key document.addEventListener("keydown", (e) => { if (e.key === "Escape" && navWrap.getAttribute("data-nav") === "open") { closeNav(); } }); } initMenu(); }); gsap.utils.toArray(".u-text em").forEach((el) => { let endVal = parseInt(el.textContent.replace(/\D/g, ""), 10); gsap.fromTo( el, { innerText: 0 }, { innerText: endVal, duration: 2, ease: "power1.out", snap: { innerText: 1 }, scrollTrigger: { trigger: el, start: "top 100%", }, onUpdate: () => { el.textContent = Math.floor(el.innerText); }, } ); }); onDesktop(() => { if (document.querySelector(".why_section")) { const cardIn = gsap.timeline({ scrollTrigger: { trigger: ".why_section", start: "clamp(top 85%)", end: "clamp(top 40%)", scrub: true, }, }); cardIn.fromTo( ".card_2", { opacity: 0, yPercent: 100, rotateZ: (index) => (index < 2 ? -45 : 45), }, { opacity: 1, yPercent: 0, rotateZ: 0, stagger: { each: 0.03, from: "center" }, ease: "power1.out", } ); } }); $(".fade-in").each(function () { let fadeIn = $(this); const fadeInTl = gsap.timeline({ scrollTrigger: { trigger: $(this), start: "clamp(top 95%)", toggleActions: "play none none none", }, }); fadeInTl.fromTo( fadeIn, { opacity: 0, y: "3rem", }, { opacity: 1, y: "0rem", } ); }); $(".ymove").each(function () { let parallaxImgWrap = $(this); let parallaxImg = parallaxImgWrap.find("img"); const imgScrollTimeline = gsap.timeline({ scrollTrigger: { trigger: $(this), start: "clamp(top bottom)", end: "clamp(bottom top)", scrub: true, }, }); imgScrollTimeline.fromTo( parallaxImg, { yPercent: 0 }, { yPercent: 10, ease: "linear" } ); }); $(".fade-out").each(function () { let fadeOut = $(this); const fadeOutTl = gsap.timeline({ scrollTrigger: { trigger: fadeOut, start: "clamp(bottom 70%)", end: "clamp(bottom top)", scrub: true, }, }); fadeOutTl.fromTo(fadeOut, { opacity: 0 }, { opacity: 1, ease: "linear" }); }); //anchor links const anchorLinks = document.querySelectorAll('.anchor_holder a[href^="#"]'); const sectionIds = Array.from(anchorLinks) .map((link) => link.getAttribute("href").substring(1)) .filter((id) => document.getElementById(id)); const sections = sectionIds.map((id) => document.getElementById(id)); const anchorHolders = document.querySelectorAll(".anchor_holder"); let isScrolling = false; const observerOptions = { root: null, rootMargin: "-20% 0px -70% 0px", threshold: 0, }; const observer = new IntersectionObserver((entries) => { if (isScrolling) return; // Ignore during programmatic scroll entries.forEach((entry) => { if (entry.isIntersecting) { const sectionId = entry.target.id; // Remove active from all anchorHolders.forEach((h) => { h.classList.remove("active", "w--current"); }); // Add active to matching anchor const activeLink = document.querySelector( `.anchor_holder a[href="#${sectionId}"]` ); if (activeLink) { activeLink .closest(".anchor_holder") .classList.add("active", "w--current"); } } }); }, observerOptions); // Observe all sections sections.forEach((section) => observer.observe(section)); // Click handlers anchorHolders.forEach((holder) => { const link = holder.querySelector('a[href^="#"]'); if (link) { link.addEventListener("click", function (e) { isScrolling = true; // Remove active from all holders anchorHolders.forEach((h) => { h.classList.remove("active", "w--current"); }); // Add active to clicked holder holder.classList.add("active", "w--current"); // Re-enable observer after scroll completes setTimeout(() => { isScrolling = false; }, 1000); }); } }); // Set active based on current hash on page load function setActiveFromHash() { const hash = window.location.hash; if (hash) { anchorHolders.forEach((h) => { const link = h.querySelector('a[href^="#"]'); if (link && link.getAttribute("href") === hash) { h.classList.add("active", "w--current"); } else { h.classList.remove("active", "w--current"); } }); } } setActiveFromHash(); window.addEventListener("hashchange", setActiveFromHash); //pageload