let mm = gsap.matchMedia(); 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("primary-ease", "M0,0 C0.15,0 0.15,1 1,1"); CustomEase.create( "slideEase", "M0,0 C0.071,0.505 0.192,0.726 0.318,0.852 0.45,0.984 0.504,1 1,1" ); function removeConditionalElements() { $(".w-condition-invisible").remove(); } let screensaverEl = $(".screensaver"); let screensaverBg = $(".screensaver-bg"); let screenSaverLottie = $(".screensaver-lottie"); let screenSaverProgress = $(".screensaver-progress"); $(".date").text(new Date().getFullYear()); const lenis = new Lenis(); // lenis.on("scroll", ScrollTrigger.update); gsap.ticker.add((time) => { lenis.raf(time * 1000); }); gsap.ticker.lagSmoothing(0); function afterPreloader() { let panels = $(".load_grid-item"); let panelColor = $(".load-grid_item-2"); let pageTransitionEl = $(".load_grid"); let preloader = $(".preloader-component"); let pageOutTl = gsap.timeline({ defaults: { duration: 0.8, }, onComplete: () => { sessionStorage.setItem("preloaderShown", "true"); document.documentElement.classList.remove("show-preloader"); }, }); pageOutTl.set(".load_grid", { display: "flex", }); pageOutTl.fromTo( ".load_grid-item", { width: "0%", }, { width: "100%", stagger: { each: 0.065, from: "random", }, ease: "power2.in", }, "<" ); pageOutTl.fromTo( ".load_bg", { opacity: 0, }, { opacity: 1, ease: "power1.out", }, "<" ); pageOutTl.set(preloader, { display: "none", }); pageOutTl.to(".load_grid-item", { width: "0%", stagger: { each: 0.065, from: "random", }, ease: "power2.inOut", }); pageOutTl.to( ".load_bg", { opacity: 0, ease: "power1.out", }, "<" ); pageOutTl.set(pageTransitionEl, { display: "none", }); } //preloader things let counter = { value: 0, }; let loaderDuration = 2; function updateLoaderText() { let progress = Math.round(counter.value); $(".progress-number").text(progress); } function runPreloader() { let pageReloadTl = gsap.timeline({ onComplete: () => { afterPreloader(); }, }); pageReloadTl.to(counter, { value: 100, onUpdate: updateLoaderText, duration: loaderDuration, ease: "loaderEase", }); } function checkAndRunPreloader() { if (!sessionStorage.getItem("preloaderShown")) { runPreloader(); } else { document.querySelector(".preloader-component").style.display = "none"; } } checkAndRunPreloader(); // function nextPrev() { // const currentArticleNumber = parseInt($(".current-project").text()); // // Store the parent container reference before removing elements // const $parentContainer = $(".next-work_item").first().parent(); // const $parentContainerAlt = $(".next-work_item-alt").first().parent(); // // Collect all valid projects with their numbers before removing any // const projects = []; // $(".next-work_item").each(function () { // const num = parseInt($(this).find(".next-project_name").text()); // if (!isNaN(num)) { // projects.push({ element: $(this).clone()[0], number: num }); // } // }); // const projectsAlt = []; // $(".next-work_item-alt").each(function () { // const num = parseInt($(this).find(".next-project_name").text()); // if (!isNaN(num)) { // projectsAlt.push({ element: $(this).clone()[0], number: num }); // } // }); // projects.sort((a, b) => a.number - b.number); // projectsAlt.sort((a, b) => a.number - b.number); // let nextProject = projects.find((p) => p.number > currentArticleNumber); // let nextProjectAlt = projectsAlt.find((p) => p.number > currentArticleNumber); // if (!nextProject && projects.length > 1) { // const firstProject = projects[0]; // if (firstProject.number !== currentArticleNumber) { // nextProject = firstProject; // } // } // if (!nextProjectAlt && projectsAlt.length > 1) { // const firstProjectAlt = projectsAlt[0]; // if (firstProjectAlt.number !== currentArticleNumber) { // nextProjectAlt = firstProjectAlt; // } // } // $(".next-work_item").remove(); // $(".next-work_item-alt").remove(); // if (nextProject && $parentContainer.length > 0) { // const $selectedElement = $(nextProject.element); // $selectedElement.addClass("current-next"); // $parentContainer.append($selectedElement); // } // if (nextProjectAlt && $parentContainerAlt.length > 0) { // const $selectedElementAlt = $(nextProjectAlt.element); // $selectedElementAlt.addClass("current-next"); // $parentContainerAlt.append($selectedElementAlt); // } // } // nextPrev(); function init() { removeConditionalElements(); function setupNextProjectNavigation() { // Get current page URL (without hash or query params for clean comparison) const currentURL = window.location.pathname; // Get all collection items with next-project_link const collectionItems = document.querySelectorAll(".next-work_item"); if (collectionItems.length === 0) { console.error('No collection items found with class "next-work_item"'); return; } // Build array of items with their URLs const projectItems = []; collectionItems.forEach((item, index) => { const linkElement = item.querySelector(".next-project_link"); if (linkElement && linkElement.href) { // Extract pathname for comparison (removes domain, hash, query params) const itemURL = new URL(linkElement.href).pathname; projectItems.push({ element: item, url: itemURL, linkElement: linkElement, index: index, }); } }); if (projectItems.length === 0) { console.error("No valid project links found"); return; } // Find current project in the collection let currentIndex = -1; projectItems.forEach((project, index) => { if (project.url === currentURL) { currentIndex = index; } }); if (currentIndex === -1) { console.error("Current page not found in collection"); console.log("Current URL:", currentURL); console.log( "Available URLs:", projectItems.map((p) => p.url) ); return; } // Calculate next index (loop back to 0 if at end) const nextIndex = (currentIndex + 1) % projectItems.length; const nextProject = projectItems[nextIndex]; // Remove all collection items except the next one from the DOM projectItems.forEach((project, index) => { if (index !== nextIndex) { // Get the parent collection item (usually .w-dyn-item) const collectionItem = project.element.closest(".w-dyn-item") || project.element.parentElement; if (collectionItem) { collectionItem.remove(); } } }); console.log(`Current: ${currentURL} (index ${currentIndex})`); console.log(`Next: ${nextProject.url} (index ${nextIndex})`); // Store next URL globally for easy access window.nextProjectURL = nextProject.url; window.nextProjectLink = nextProject.linkElement; } // Run the setup function updateTime() { const options = { timeZone: "Europe/London", hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit", }; $(".current-time").text(new Date().toLocaleTimeString("en-GB", options)); } setInterval(updateTime, 1000); updateTime(); $("[count-items=wrap]").each(function () { const countWrap = $(this); const itemCount = countWrap.find("[count-items=item]").length; countWrap .find("[count-items=total]") .text(itemCount.toString().padStart(2, "0")); }); let splitText; let richTextSplit; let stickySplit; function runSplit() { splitText = new SplitType("[split-it]", { types: "lines, words, chars", lineClass: "s-l", wordClass: "s-w", charClass: "s-c", }); richTextSplit = new SplitType("[split-rich] p", { types: "lines, words", lineClass: "s-l", wordClass: "s-w", charClass: "s-c", }); stickySplit = new SplitType("[team-split] p", { types: "lines, words", lineClass: "s-l", }); } runSplit(); let windowWidth = $(window).innerWidth(); window.addEventListener("resize", function () { if (windowWidth !== $(window).innerWidth()) { windowWidth = $(window).innerWidth(); splitText.revert(); richTextSplit.revert(); stickySplit.revert(); runSplit(); } }); $("[scroll-split] , [split-rich] p").each(function (index) { let contentLines = $(this).find(".s-l"); let tl = gsap.timeline({ scrollTrigger: { trigger: contentLines, start: "top 90%", toggleActions: "play none none none", }, }); tl.fromTo( contentLines, { yPercent: 100, clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", }, { yPercent: 0, clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", ease: "expo.out", duration: 0.5, stagger: 0.05, } ); }); $("[pload-split]").each(function (index) { let contentLines = $(this).find(".s-l"); let tl = gsap.timeline({}); tl.fromTo( "[pload-split]", { opacity: 0, }, { opacity: 1, ease: "power3.out", duration: 0.3, } ); tl.fromTo( contentLines, { yPercent: 100, clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", }, { yPercent: 0, clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", ease: "expo.out", duration: 1, stagger: 0.05, } ); }); //Home Slider $(".hero-slider").each(function () { let childItems = $(this).find(".hero-slider_item").hide(); let slideNumber = $(this).find(".hero-slider_nav-item"); let slideTrigger = slideNumber.find(".hero-slider_num"); let activeIndex = 0; let totalSlides = childItems.length; childItems.first().css("display", "flex"); slideNumber.first().addClass("active"); function generateMaskBars(numBars) { var startState = ""; var endState = ""; var currentPosition = 0; var remainingWidth = 100; for (var i = 0; i < numBars; i++) { var maxVariation = (100 / numBars) * 0.8; var baseWidth = 100 / numBars; var barWidth = baseWidth + (Math.random() * maxVariation - maxVariation / 2); if (i === numBars - 1) { barWidth = remainingWidth; } var startPercent = currentPosition; var endPercent = startPercent + barWidth; startState += `black ${startPercent}% ${endPercent}%, transparent ${endPercent}% ${endPercent}%, `; endState += `black ${startPercent}% ${startPercent}%, transparent ${startPercent}% ${endPercent}%, `; currentPosition = endPercent; remainingWidth -= barWidth; if (currentPosition >= 100) break; } startState = startState.slice(0, -2); endState = endState.slice(0, -2); return { startState, endState }; } function moveSlide(nextIndex, forwards) { let prevItem = childItems.eq(activeIndex); let nextItem = childItems.eq(nextIndex); let prevItemImg = childItems.eq(activeIndex).find(".hero-visual_el"); let nextItemImg = childItems.eq(nextIndex).find(".hero-visual_el"); // Set both slides to display flex prevItem.css("display", "flex"); nextItem.css("display", "flex"); gsap.set(childItems, { zIndex: -1 }); // Position the next item on top gsap.set(nextItem, { zIndex: 2 }); gsap.set(prevItem, { zIndex: 1 }); let { startState, endState } = generateMaskBars(5); if (forwards) { // Moving forward gsap.set(nextItem, { "--mask-section": endState, maskImage: "linear-gradient(90deg, var(--mask-section))", WebkitMaskImage: "linear-gradient(90deg, var(--mask-section))", // scale: 1.2, // transformOrigin: "center right ", }); gsap.set(nextItemImg, { scale: 1.2, transformOrigin: "center right ", }); gsap.set(prevItem, { "--mask-section": startState, maskImage: "linear-gradient(90deg, var(--mask-section))", WebkitMaskImage: "linear-gradient(90deg, var(--mask-section))", }); } else { // Moving backward gsap.set(nextItem, { "--mask-section": endState, maskImage: "linear-gradient(270deg, var(--mask-section))", WebkitMaskImage: "linear-gradient(270deg, var(--mask-section))", }); gsap.set(nextItemImg, { scale: 1.2, transformOrigin: "center left", }); gsap.set(prevItem, { "--mask-section": startState, maskImage: "linear-gradient(270deg, var(--mask-section))", WebkitMaskImage: "linear-gradient(270deg, var(--mask-section))", }); } let tl = gsap.timeline({ defaults: { duration: 0.8, ease: "expo.out" }, }); if (forwards) { tl.to(nextItem, { "--mask-section": startState, }); tl.to( nextItemImg, { scale: 1, }, "<" ); } else { tl.to(nextItem, { "--mask-section": startState, }); tl.to( nextItemImg, { scale: 1, }, "<" ); } // Update dots slideNumber.removeClass("active"); slideNumber.eq(nextIndex).addClass("active"); activeIndex = nextIndex; } // CLICK ON DOTS mm.add("(min-width: 992px)", () => { slideNumber.on("mousemove", function () { let dotIndex = $(this).index(); if ($(this).hasClass("active")) return; slideNumber.removeClass("active"); $(this).addClass("active"); moveSlide(dotIndex, activeIndex < dotIndex); }); }); // SWIPE FUNCTIONALITY USING Hammer.js let hammer = new Hammer(this); hammer.on("swiperight", function () { let nextIndex = activeIndex + 1; if (nextIndex >= totalSlides) { nextIndex = 0; // Loop back to the first slide } moveSlide(nextIndex, true); }); hammer.on("swipeleft", function () { let prevIndex = activeIndex - 1; if (prevIndex < 0) { prevIndex = totalSlides - 1; // Loop back to the last slide } moveSlide(prevIndex, false); }); }); $("[trigger-overlay]").on("mouseenter", function () { $(".page_wrap").addClass("clip-overflow"); }); $("[trigger-overlay]").on("mouseleave", function () { $(".page_wrap").removeClass("clip-overflow"); }); let menuTl; // nav-wrap $(".nav-wrap").each(function () { let menu = $(".nav-menu"); let menuDropdown = $(".nav-menu_dropdown"); let menuItems = menuDropdown.find(".menu-item"); menuTl = gsap.timeline({ paused: true, }); menuTl.fromTo( menuItems, { yPercent: -100, clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { yPercent: 0, clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", ease: "slideEase", duration: 0.4, stagger: { from: "random", each: 0.025, }, } ); // mm.add("(min-width: 992px)", () => { menu.on("mouseenter", function () { $(this).addClass("show-dropdown"); menuTl.play(); }); }); menu.on("mouseleave", function () { $(this).removeClass("show-dropdown"); menuTl.reverse(); }); mm.add("(max-width: 991px)", () => { menu.on("click", function () { if ($(this).hasClass("show-dropdown")) { $(this).removeClass("show-dropdown"); menuTl.reverse(); } else { $(this).addClass("show-dropdown"); menuTl.play(); } }); }); }); $("[dropdown='trigger']").each(function () { let dropdownTrigger = $(this); let dropdownEl = dropdownTrigger.find("[dropdown='hidden']"); dropdownTrigger.on("mouseenter mouseleave", function () { dropdownEl.toggleClass("show-menu"); }); }); $(".grid-list_toggle").each(function () { let gridToggle = $(".grid-toggle"); let listToggle = $(".index-toggle"); let body = $(".work-page"); listToggle.on("click", function () { body.removeClass("grid-view"); body.addClass("list-view"); $(".grid-toggle").removeClass("active"); $(".index-toggle").addClass("active"); lenis.scrollTo(0, { duration: 1, }); lenis.resize(); ScrollTrigger.refresh(); }); gridToggle.on("click", function () { body.addClass("grid-view"); body.removeClass("list-view"); $(".grid-toggle").addClass("active"); $(".index-toggle").removeClass("active"); lenis.scrollTo(0, { duration: 1, }); lenis.resize(); ScrollTrigger.refresh(); }); }); // nextPrev(); $("[mouse-track=component]").each(function () { let cloneHolder = $(this); let holder = cloneHolder.find("[mouse-track=element]"); let delayHolders = cloneHolder.find("[mouse-track=clone]"); mm.add("(min-width: 992px)", () => { cloneHolder.on("mousemove", function (e) { let layoutBounds = cloneHolder[0].getBoundingClientRect(); let mouseX = e.clientX - layoutBounds.left; let percentX = mouseX / layoutBounds.width; percentX = (percentX - 0.2) / 0.6; percentX = Math.max(0, Math.min(1, percentX)); let maxShift = layoutBounds.width - holder.outerWidth(); let marginLeft = percentX * maxShift; gsap.to(holder, { marginLeft: marginLeft, duration: 0.3, ease: "power3.out", }); gsap.to(delayHolders, { marginLeft: marginLeft, duration: 0.6, delay: 0.05, stagger: { amount: 0.2, from: "end", }, ease: "power3.out", }); }); }); }); mm.add("(min-width: 992px)", () => { $(".work-list_item").on("mousemove", function () { $(this).addClass("show-clones"); }); $(".work-list_item").on("mouseleave", function () { $(this).removeClass("show-clones"); }); }); //Single Work Scrolltriggers $(".single-page_wrap").each(function () { let singlePage = $(this); let singleTrigger = singlePage.find(".single-work_hero-wrap"); let singleSticky = singlePage.find(".single-info_contain"); let singleButton = singlePage.find(".single-work_btn"); let singleInfoTL = gsap.timeline({ scrollTrigger: { trigger: singleTrigger, start: "top top", end: "bottom top", scrub: true, }, defaults: { ease: "none" }, }); mm.add("(min-width: 992px)", () => { singleInfoTL.to(singleSticky, { paddingTop: "3.5rem", }); ScrollTrigger.create({ trigger: singleTrigger, start: "bottom center", // end: "bottom top", onEnter: () => { singleButton.addClass("show"); }, onLeaveBack: () => { singleButton.removeClass("show"); }, }); }); }); $("[infinite-wrap]").each(function () { //Infinite Directors let contactBg = $(this).find(".contact-page_bg"); let directorBG = $(this).find(".director-img_bg img"); const infiniteTrigger = $(this)[0]; const menuElement = document.querySelector("[infinite-list]"); const menuItemElements = document.querySelectorAll("[infinite-item]"); // const bgImage = document.querySelectorAll(".director-img_bg"); // let menuElementHeight = menuElement.clientHeight; let menuItemHeight = menuItemElements[0].clientHeight; let totalMenuHeight = menuItemElements.length * menuItemHeight; let currentScrollPosition = 0; let lastScrollY = 0; let smoothScrollY = 0; const interpolate = (start, end, factor) => start * (1 - factor) + end * factor; const adjustMenuItemsPosition = (scroll) => { gsap.set(menuItemElements, { y: (index) => index * menuItemHeight + scroll, modifiers: { y: (y) => { const wrappedY = gsap.utils.wrap( -menuItemHeight, totalMenuHeight - menuItemHeight, parseInt(y) ); return `${wrappedY}px`; }, }, }); if (contactBg.length) { gsap.to(contactBg, { backgroundPosition: `0px ${-scroll * 0.05}px`, }); } }; adjustMenuItemsPosition(0); const onWheelScroll = (event) => { mm.add("(min-width: 992px)", () => { currentScrollPosition -= event.deltaY; $(".director-inf_item").removeClass("active"); // if (directorBG.length) { // gsap.to(".director-img_bg img", { // clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", // duration: 1, // ease: "power3.out", // }); // } }); }; let startY = 0; let currentY = 0; let isDragging = false; const onDragStart = (event) => { startY = event.clientY || event.touches[0].clientY; isDragging = true; menuElement.classList.add("is-dragging"); }; const onDragMove = (event) => { if (!isDragging) return; currentY = event.clientY || event.touches[0].clientY; currentScrollPosition += (currentY - startY) * 3; startY = currentY; }; const onDragEnd = () => { isDragging = false; menuElement.classList.remove("is-dragging"); }; const animate = () => { requestAnimationFrame(animate); smoothScrollY = interpolate(smoothScrollY, currentScrollPosition, 0.1); adjustMenuItemsPosition(smoothScrollY); const scrollSpeed = smoothScrollY - lastScrollY; lastScrollY = smoothScrollY; gsap.to(menuItemElements, { scale: 1 - Math.min(100, Math.abs(scrollSpeed)) * 0.001, // rotate: scrollSpeed * 0.2, }); }; animate(); infiniteTrigger.addEventListener("mousewheel", onWheelScroll); infiniteTrigger.addEventListener("touchstart", onDragStart); infiniteTrigger.addEventListener("touchmove", onDragMove); infiniteTrigger.addEventListener("touchend", onDragEnd); infiniteTrigger.addEventListener("mousedown", onDragStart); infiniteTrigger.addEventListener("mousemove", onDragMove); infiniteTrigger.addEventListener("mouseleave", onDragEnd); infiniteTrigger.addEventListener("mouseup", onDragEnd); infiniteTrigger.addEventListener("selectstart", () => false); window.addEventListener("resize", () => { menuElementHeight = menuElement.clientHeight; menuItemHeight = menuItemElements[0].clientHeight; totalMenuHeight = menuItemElements.length * menuItemHeight; }); // Initialize image containers const imageContainers = document.querySelectorAll(".director-cms_img-item"); const backgroundContainer = document.querySelector(".director-img_bg"); let previousIndex = -1; // Set up image data attributes imageContainers.forEach((container) => { const hiddenImg = container.querySelector(".hidden-directors_img"); if (hiddenImg && hiddenImg.src) { container.setAttribute("data-img-src", hiddenImg.src); } }); // Image append function const appendImage = (index) => { if (!backgroundContainer) return; const container = imageContainers[index]; if (!container) return; const imgSrc = container.dataset.imgSrc; if (!imgSrc) return; const img = document.createElement("img"); img.src = imgSrc; img.style.clipPath = "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)"; img.style.position = "absolute"; img.style.width = "100%"; img.style.height = "100%"; img.style.objectFit = "cover"; backgroundContainer.appendChild(img); gsap.to(img, { clipPath: "polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%)", duration: 1, ease: "power3.out", onComplete: function () { removeExtraImages(backgroundContainer); }, }); }; // Remove extra images function function removeExtraImages(container) { while (container.children.length > 5) { container.removeChild(container.firstChild); } } mm.add("(min-width: 992px)", () => { $(".directors-name_wrap").on("mouseenter", function () { const parentItem = $(this).closest(".director-inf_item"); const index = $(".director-inf_item").index(parentItem); // Add active class parentItem.addClass("active"); // Animate content lines let contentLines = parentItem.find(".s-l"); gsap.fromTo( contentLines, { yPercent: 100, clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", }, { yPercent: 0, clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", ease: "primary-ease", duration: 0.6, stagger: 0.07, overwrite: true, } ); // Handle image animation // if (previousIndex !== index) { appendImage(index); // } previousIndex = index; }); $(".directors-name_wrap").on("mouseleave", function () { $(this).closest(".director-inf_item").removeClass("active"); }); $(".director-inf_item").on("mouseleave", function () { gsap.to(".director-img_bg img", { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", duration: 1, ease: "power3.out", }); }); }); }); $(".page-main").each(function () { let pageEl = $(this); let cursorItem = pageEl.find(".cursor"); let cursorParagraph = cursorItem.find("p"); let targets = pageEl.find("[data-cursor]"); let contactPage = pageEl.find(".is-contact"); let xOffset = 50; let yOffset = 50; let cursorIsOnRight = false; let currentTarget = null; let lastText = ""; gsap.set(cursorItem, { xPercent: xOffset, yPercent: yOffset }); let xTo = gsap.quickTo(cursorItem[0], "x", { ease: "power3" }); let yTo = gsap.quickTo(cursorItem[0], "y", { ease: "power3" }); $(window).on("mousemove", function (e) { let windowWidth = $(window).width(); let windowHeight = $(window).height(); let scrollY = $(window).scrollTop(); let cursorX = e.clientX; let cursorY = e.clientY + scrollY; let xPercent = xOffset; let yPercent = yOffset; if (cursorX > windowWidth * 0.9) { cursorIsOnRight = true; xPercent = -100; } else { cursorIsOnRight = false; } if (cursorY > scrollY + windowHeight * 0.9) { yPercent = -120; } if (currentTarget) { let newText = currentTarget.attr("data-cursor"); if (currentTarget.is("[data-easteregg]") && cursorIsOnRight) { newText = currentTarget.attr("data-easteregg"); } if (newText !== lastText) { cursorParagraph.html(newText); lastText = newText; } } gsap.to(cursorItem, { xPercent: xPercent, yPercent: yPercent, duration: 0.9, ease: "power3", }); xTo(cursorX); yTo(cursorY - scrollY); }); targets.each(function () { let target = $(this); target.on("mouseover", function () { currentTarget = target; let newText = target.is("[data-easteregg]") ? target.attr("data-easteregg") : target.attr("data-cursor"); if (newText !== lastText) { cursorParagraph.html(newText); lastText = newText; } }); }); function screenSaver() { let screensaverBuildup = false; let showScreenSaver = gsap.timeline({ paused: true, defaults: { ease: "power1.inOut", duration: 1.8, }, onReverseComplete: () => { screensaverBuildup = false; screensaverEl.removeClass("show-screensaver"); }, }); showScreenSaver.fromTo( screensaverEl, { clipPath: " polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)", }, { delay: 0.5, clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", duration: 1.2, ease: "power2.out", onComplete: () => { screensaverBuildup = true; screensaverEl.addClass("show-screensaver"); }, } ); showScreenSaver.fromTo( screenSaverLottie, { opacity: 0, }, { opacity: 1, ease: "primary-ease", duration: 0.5, }, "<" ); let hideScreenSaver = gsap.timeline({ paused: true, defaults: { ease: "power2.out", duration: 0.6, }, onComplete: () => { showScreenSaver.progress(0).pause(); }, }); hideScreenSaver.to(screensaverEl, { clipPath: " polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)", duration: 0.5, }); pageEl.on("mousedown touchstart", function (event) { // Prevent right-click from triggering if (event.button === 2) return; // Right-click on desktop if (event.touches && event.touches.length > 1) return; // Multi-touch on mobile showScreenSaver.timeScale(1); showScreenSaver.play(); }); pageEl.on("mouseup touchend", function () { if (screensaverBuildup === false) { showScreenSaver.timeScale(2); showScreenSaver.reverse(); } }); screensaverEl.on("click", function () { hideScreenSaver.restart(); screensaverEl.removeClass("show-screensaver"); }); } if (!document.querySelector(".contact-page_bg")) { screenSaver(); } if (document.querySelector(".single-wrap")) { setTimeout(function () { setupNextProjectNavigation(); }, 10); } }); //home slider_nav $(".home-page").each(function (index) { let navTrigger = $(this).find("[nav-trigger]"); let navLogo = $(this).find(".nav-logo"); mm.add("(min-width: 992px)", () => { let navShrinkTl = gsap.timeline(); navShrinkTl.to(navLogo, { scrollTrigger: { trigger: $(this), start: "clamp(top 40px)", end: "top top", endTrigger: navTrigger, scrub: true, }, width: "9rem", ease: "linear", }); }); }); //home slider_nav $(".page_wrap").each(function () { let footerMenu = $(this).find("[footer-trigger]"); let contactPage = $(this).find(".contact-right"); let footerTextTl = gsap.timeline({ paused: true }); if (footerMenu.length) { ScrollTrigger.create({ trigger: footerMenu, start: "top center", end: "top top", // markers: true, onEnter: () => { // ScrollTrigger.refresh(); menuTl.play(); footerTextTl.play(); }, onLeaveBack: () => { menuTl.reverse(); footerTextTl.reverse(); }, }); } let footerCols = footerMenu.find("[footer-col]"); let contactItems = contactPage.find(".contact-item"); footerCols.each(function (colIndex) { let splitItems = $(this).find("[split-it]"); let splitLines = splitItems.find(".s-l"); footerTextTl.add( gsap.fromTo( splitLines, { clipPath: "polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)", }, { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", stagger: { each: 0.05 }, duration: 0.5, } ), "<" // colIndex * 0.25 ); }); let introClip = gsap.timeline({ delay: 0.5, }); contactItems.each(function (colIndex) { let splitItems = $(this).find("[split-it]"); let splitLines = splitItems.find(".s-l"); introClip.add( gsap.fromTo( splitLines, { clipPath: "polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%)", }, { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", stagger: { each: 0.05 }, duration: 0.5, } ), "<" // colIndex * 0.25 ); }); }); $(".culture-grid_item").each(function (index) { let group = Math.floor(index / 9); let rowOffset = group * 6; $(this).css("grid-row-start", rowOffset + getRow(index % 9)); }); function getRow(pos) { const rowMapping = [1, 2, 2, 3, 3, 3, 4, 4, 5]; return rowMapping[pos]; } gsap.registerPlugin(Flip); // Constants for class names const POSITION_CLASSES = { WEST: "pos-west", EAST: "pos-east", }; const DIRECTIONS = ["pos-west", "pos-east"]; // Selecting DOM elements const $gridElement = $(".culture-grid_list"); const $gridItems = $gridElement.find(".culture-grid_item"); const $gridImages = $gridElement.find(".culture-visual_wrap"); const $fullscreenElement = $(".fullscreen"); // Flag to track fullscreen mode let isFullscreen = false; // Animation defaults const animationDefaults = { duration: 0.6, ease: "expo" }; // Function to flip the clicked image and animate its movement const flipImage = ($gridItem, $gridImage) => { gsap.set($gridItem, { zIndex: 99 }); const state = Flip.getState($gridImage[0]); if (isFullscreen) { gsap.set($fullscreenElement, { pointerEvents: "none" }); $gridItem.append($gridImage); lenis.start(); } else { gsap.set($fullscreenElement, { pointerEvents: "auto" }); $fullscreenElement.append($gridImage); lenis.stop(); } Flip.from(state, { ...animationDefaults, scale: true, prune: true, onComplete: () => { if (isFullscreen) { gsap.set($gridItem, { zIndex: "auto" }); } isFullscreen = !isFullscreen; }, }); }; // Function to determine the direction class from data attribute const determineDirectionClassFromData = ($gridItem) => { const direction = $gridItem.data("direction-items"); switch (direction) { case "west": return POSITION_CLASSES.WEST; case "east": return POSITION_CLASSES.EAST; default: // If no valid direction is specified, use a random direction return determineRandomDirectionClass(); } }; // Function to determine a random direction class const determineRandomDirectionClass = () => { const randomIndex = Math.floor(Math.random() * DIRECTIONS.length); return DIRECTIONS[randomIndex]; }; // Function to move other items based on their position relative to the clicked item const moveOtherItems = ($gridItem, directionClass) => { // For the remaining images const otherGridItems = $gridItems.not($gridItem); const state = Flip.getState(otherGridItems.toArray()); otherGridItems.each(function () { if (directionClass) { $(this).toggleClass(directionClass, !isFullscreen); } }); Flip.from(state, { ...animationDefaults, scale: true, prune: true, }); }; // Click event handler for the grid images const toggleImage = function () { const $gridImage = $(this); const $gridItem = $gridItems.eq($gridImage.data("index")); flipImage($gridItem, $gridImage); const directionClass = determineDirectionClassFromData($gridItem); moveOtherItems($gridItem, directionClass); }; // Function to initialize event listeners for grid images const initEvents = () => { $gridImages.each(function (index) { // Save the index of the image $(this).data("index", index); // Add click event listener to the image $(this).on("click", toggleImage); }); }; initEvents(); //lottie vibes $("[lottie-wrap]").each(function (index) { let lottieHolder = $(this).find("[lottie-holder]"); let lottieFile = $(this).find("[lottie-element]"); let lottieUrl = lottieFile.attr("lottie-url"); let animationType = lottieHolder.attr("lottie-holder"); let lottieAnimation = bodymovin.loadAnimation({ container: lottieFile[0], renderer: "svg", autoplay: animationType === "loop", loop: animationType === "loop", path: lottieUrl, }); if (animationType === "scrub") { setTimeout(function () { if (!lottieAnimation.totalFrames) { console.error("Lottie animation not loaded properly."); return; } // lottieAnimation.loop = false; gsap.to(lottieAnimation, { scrollTrigger: { trigger: lottieHolder, start: "top bottom", end: "bottom top", scrub: 0.1, onUpdate: (self) => { let progress = self.progress; let frame = progress * lottieAnimation.totalFrames - 1; lottieAnimation.goToAndStop(frame, true); }, }, }); }, 1000); } }); $(".team-section").each(function () { function generateMaskBars(numBars) { var startState = ""; var endState = ""; var currentPosition = 0; var remainingWidth = 100; // Ensure we use the full 100% for (var i = 0; i < numBars; i++) { var maxVariation = (100 / numBars) * 0.8; // Adjust the randomness (40% variation) var baseWidth = 100 / numBars; var barWidth = baseWidth + (Math.random() * maxVariation - maxVariation / 2); // Slight variation if (i === numBars - 1) { barWidth = remainingWidth; // Ensure last bar reaches 100% } var startPercent = currentPosition; var endPercent = startPercent + barWidth; startState += `black ${startPercent}% ${endPercent}%, transparent ${endPercent}% ${endPercent}%, `; endState += `black ${startPercent}% ${startPercent}%, transparent ${startPercent}% ${endPercent}%, `; currentPosition = endPercent; remainingWidth -= barWidth; if (currentPosition >= 100) break; } startState = startState.slice(0, -2); endState = endState.slice(0, -2); return { startState: startState, endState: endState }; } var teamSection = $(this); var childItems = teamSection.find(".team-item"); var teamTriggers = teamSection.find(".team-trig_item"); let activeIndex = 0; teamTriggers.each(function (index) { var currentTrigger = $(this); var currentTeamItem = childItems.eq(index); var imgWraps = currentTeamItem.find(".team-img_wrap"); let imgEl = imgWraps.find("img"); var { startState, endState } = generateMaskBars(5); imgWraps.each(function () { var imgWrap = $(this); gsap.set(imgWrap, { mask: "linear-gradient(180deg,var(--mask-section))", }); var clipTl = gsap.timeline({ scrollTrigger: { trigger: currentTrigger, start: "top bottom", end: "bottom bottom", scrub: true, }, }); clipTl.fromTo( imgWrap, { "--mask-section": endState, }, { "--mask-section": startState, ease: "none", } ); clipTl.fromTo( imgEl, { scale: 1.1, }, { scale: 1, ease: "none", }, "<" ); clipTl.to(imgEl, { duration: 0.5, }); }); // gsap.set(childItems.find("[team-fade]"), { yPercent: 120 }); gsap.set(childItems.find("[team-num]"), { yPercent: 120 }); gsap.set(childItems.find("[team-split]"), { opacity: 0 }); function moveSlide(nextIndex, forwards) { let prevItem = childItems.eq(activeIndex); let nextItem = childItems.eq(nextIndex); if (nextIndex === activeIndex && activeIndex !== 0) return; let prevTeamFade = prevItem.find("[team-fade]"); let prevTeamNum = prevItem.find("[team-num]"); let prevTeamSplit = prevItem.find("[team-split]"); let nextTeamFade = nextItem.find("[team-fade]"); let nextTeamNum = nextItem.find("[team-num]"); let nextTeamSplit = nextItem.find("[team-split]"); let tl = gsap.timeline({ defaults: { duration: 0.75, ease: "expo.out" }, }); if (forwards) { //names & job titles tl.to(prevTeamFade, { yPercent: -120 }); tl.to(nextTeamFade, { yPercent: 0 }, "<"); //number tl.to(prevTeamNum, { yPercent: -120 }, "<"); tl.to(nextTeamNum, { yPercent: 0 }, "<"); //writeup tl.to(prevTeamSplit, { opacity: 0 }, "<"); tl.to(nextTeamSplit, { opacity: 1 }, "<"); } else { //names & job titles tl.to(prevTeamFade, { yPercent: 120 }); tl.to(nextTeamFade, { yPercent: 0 }, "<"); //number tl.to(prevTeamNum, { yPercent: 120 }, "<"); tl.to(nextTeamNum, { yPercent: 0 }, "<"); //writeup tl.to(prevTeamSplit, { opacity: 0 }, "<"); tl.to(nextTeamSplit, { opacity: 1 }, "<"); } activeIndex = nextIndex; } gsap.timeline({ scrollTrigger: { trigger: currentTrigger, start: "top center", end: "bottom center", onEnter: () => moveSlide(index, true), onLeave: () => moveSlide(index, true), onEnterBack: () => moveSlide(index, false), onLeaveBack: () => moveSlide(index, false), }, }); }); }); $(".is-error").each(function (index) { let errorCursor = $(this).find(".error-cursor"); let errorYTl = gsap.quickTo(errorCursor[0], "y", { duration: 0.5, ease: "power3", }); // mm.add("(max-width: 991px)", () => {}); mm.add("(min-width: 992px)", () => { $(this).on("mousemove", function (e) { let cursorY = e.clientY; errorYTl(cursorY); }); }); }); //Studio floating Images $(".studio-floating_wrap").each(function (index) { let studioImgsComp = $(this); let studioImgWrap1 = studioImgsComp.find(".studio-float_left"); let studioImgWrap2 = studioImgsComp.find(".studio-float_right"); let studioFloatingTl = gsap.timeline({ scrollTrigger: { trigger: studioImgsComp, start: "top bottom", end: "bottom top", scrub: 1, }, }); // mm.add("(min-width: 992px)", () => { studioFloatingTl.fromTo( studioImgWrap1, { yPercent: 0, }, { yPercent: -50, ease: "linear", } ); studioFloatingTl.fromTo( studioImgWrap2, { yPercent: -50, }, { yPercent: 0, ease: "linear", }, "<" ); // }); }); $("[video-player]").each(function (index) { let playVidBtn = $(this).find("[video-trigger]"); let videoPopupEl = $(this).find(".video-popup"); let closeVidBtn = $(this).find("[video-close]"); let videoItem = $(this).find(".plyr_component"); let videoBg = $(this).find(".video-popup_bg"); let thisComponent = $(this); const controls = `
00:00
`; let player = new Plyr(thisComponent.find(".plyr_video")[0], { controls, resetOnEnd: true, }); let plyrControlsCursor = $(this).find(".plyr__controls"); let videoYto = gsap.quickTo(plyrControlsCursor[0], "y", { duration: 0.5, ease: "power3", }); // mm.add("(max-width: 991px)", () => {}); mm.add("(min-width: 992px)", () => { $(this).on("mousemove", function (e) { let cursorY = e.clientY; videoYto(cursorY); }); }); let videoPopupTl = gsap.timeline({ paused: true, defaults: { ease: "primary-ease", duration: 0.5, }, onStart: () => { lenis.stop(); }, onReverseComplete: () => { lenis.start(); }, }); videoPopupTl.set(videoPopupEl, { display: "flex", }); videoPopupTl.to(videoBg, { opacity: 1, }); videoPopupTl.fromTo( videoItem, { opacity: 0, }, { opacity: 1, }, "<" ); videoPopupTl.from( closeVidBtn, { opacity: 0, duration: 0.6, }, "<" ); videoPopupTl.set(videoBg, { pointerEvents: "auto", }); playVidBtn.on("click", function () { videoPopupTl.timeScale(1).restart(); player.play(); }); closeVidBtn.on("click", function () { videoPopupTl.timeScale(2).reverse(); player.pause(); }); player.on("ended", (event) => { videoPopupTl.timeScale(2).reverse(); }); }); $("[word-shift=wrap]").each(function (index) { let squeezeLine = $(this).find("[word-shift=line]"); let tl = gsap.timeline({ scrollTrigger: { trigger: $(this), start: "top bottom", end: "bottom bottom", scrub: 0.4, }, }); tl.fromTo( squeezeLine, { width: "auto", }, { width: "100%", ease: "power1.inOut", stagger: 0.1, } ); }); // work-page $(".work-page").each(function (index) { let squeezeLine = $(this).find(".page-title.is-2"); let tl = gsap.timeline({}); tl.fromTo( squeezeLine, { marginLeft: "0px", }, { marginLeft: "auto", ease: "power3.inOut", duration: 1, } ); }); // add a media query. When it matches, the associated function will run $(".work-page").each(function () { const filterTriggers = gsap.utils.toArray("[filter-trigger]"), filterAll = document.querySelector("[filter-all]"), mobileFilterAll = document.querySelector("[mobile-all]"), grid = document.querySelector(".projects-grid_list"), items = gsap.utils.toArray(".projects-grid_item"), listItems = gsap.utils.toArray(".work-list_section [filter-el]"); function updateFilters(selectedFilter) { if (selectedFilter === "all") { resetFilters(); return; } const state = Flip.getState(items); items.forEach((item) => { const matches = item.querySelector("[filter-item]").getAttribute("filter-item") === selectedFilter; if (matches) { gsap.set(item, { position: "relative", opacity: 1, visibility: "visible", }); } else { gsap.set(item, { position: "absolute", opacity: 0, visibility: "hidden", }); } }); Flip.from(state, { duration: 0.5, ease: "power2.inOut", absolute: true, onEnter: (elements) => gsap.fromTo( elements, { opacity: 0 }, { opacity: 1, duration: 0.4, delay: 0.2 } ), onStart: () => lenis.scrollTo(0, { immediate: true }), onComplete: () => { lenis.resize(); ScrollTrigger.refresh(); }, }); listItems.forEach((listItem) => { const hasMatchingChild = listItem.querySelector(`[filter-item="${selectedFilter}"]`) !== null; gsap.set(listItem, { display: hasMatchingChild ? "block" : "none" }); }); } function resetFilters() { items.forEach((item) => { gsap.set(item, { position: "relative", opacity: 1, visibility: "visible", }); }); listItems.forEach((listItem) => { gsap.set(listItem, { display: "block" }); }); lenis.scrollTo(0, { immediate: true }); lenis.resize(); ScrollTrigger.refresh(); } filterTriggers.forEach((trigger) => { trigger.addEventListener("click", () => { document .querySelectorAll("[filter-trigger], [filter-all]") .forEach((el) => el.classList.remove("current-filter")); document .querySelectorAll("[mobile-all]") .forEach((el) => el.classList.remove("current-filter")); trigger.classList.add("current-filter"); updateFilters(trigger.getAttribute("filter-trigger")); }); }); if (filterAll) { filterAll.addEventListener("click", () => { resetFilters(); document .querySelectorAll("[filter-trigger]") .forEach((el) => el.classList.remove("current-filter")); filterAll.classList.add("current-filter"); }); } if (mobileFilterAll) { mobileFilterAll.addEventListener("click", () => { resetFilters(); document .querySelectorAll("[filter-trigger]") .forEach((el) => el.classList.remove("current-filter")); mobileFilterAll.classList.add("current-filter"); }); } }); $("[img-scroll]").each(function () { let parallaxImgWrap = $(this); let parallaxImg = parallaxImgWrap.find("img"); const imgScrollTimeline = gsap.timeline({ scrollTrigger: { trigger: $(this), start: "top bottom", end: "bottom top", scrub: true, }, }); imgScrollTimeline.fromTo( parallaxImg, { yPercent: 0 }, { yPercent: 20, ease: "linear" } ); }); } // init(); const swup = new Swup({ animateHistoryBrowsing: true, }); if (document.readyState === "complete") { init(); } else { document.addEventListener("DOMContentLoaded", () => init()); } swup.hooks.replace("animation:out:await", async () => { let pageOutTl = gsap.timeline({ defaults: { duration: 1, }, onStart: () => lenis.stop(), // onComplete: () => {}, }); pageOutTl.set(".load_grid", { display: "flex", }); pageOutTl.fromTo( ".load_grid-item", { width: "0%", }, { width: "100%", stagger: { each: 0.065, from: "random", }, ease: "power2.in", }, "<" ); pageOutTl.fromTo( ".load_bg", { opacity: 0, }, { opacity: 1, ease: "power1.out", }, "<" ); pageOutTl.fromTo( ".site-info_holder-pt", { opacity: 0, }, { opacity: 1, ease: "expo.in", }, "<" ); await pageOutTl; }); swup.hooks.replace("animation:in:await", async () => { let pageTransitionIn = gsap.timeline({ defaults: { duration: 1, }, onStart: () => { $("html, body").scrollTop(0); }, onComplete: () => { lenis.start(); lenis.resize(); ScrollTrigger.refresh(); }, }); pageTransitionIn.fromTo( ".load_grid-item", { width: "100%", }, { width: "0%", stagger: { each: 0.065, from: "random", }, ease: "expo.out", } ); pageTransitionIn.fromTo( ".site-info_holder-pt", { opacity: 1, }, { opacity: 0, ease: "expo.out", }, "<" ); pageTransitionIn.fromTo( ".load_bg", { opacity: 1, }, { opacity: 0, ease: "power1.out", }, "<" ); pageTransitionIn.set(".load_grid", { display: "none" }); await pageTransitionIn; }); swup.hooks.on("page:view", () => init());