function initNewayvescript() { console.log("🔥 Reinitializing custom scripts"); // 🖱️ Custom Cursor Animation gsap.set(".cursor", { xPercent: -50, yPercent: -50 }); let xTo = gsap.quickTo(".cursor", "x", { duration: 0.3, ease: "power2" }); let yTo = gsap.quickTo(".cursor", "y", { duration: 0.3, ease: "power2" }); window.addEventListener("mousemove", e => { xTo(e.clientX); yTo(e.clientY); }); // 🔤 Split Text Animation requestAnimationFrame(() => { const splitTarget = document.querySelector('.h1'); if (splitTarget) { // Optional cleanup if SplitType may have been used before if (splitTarget._splitType) { splitTarget._splitType.revert(); } const split = new SplitType(splitTarget, { types: 'lines, words, chars' }); splitTarget._splitType = split; // store for later cleanup split.lines.forEach(line => { gsap.from(line.querySelectorAll('.char'), { y: '100%', opacity: 0, stagger: 0.03, duration: 0.5, ease: 'power2.out' }); }); } }); // 🖼️ Case Study Scroll / Swiper Logic const wrapper = document.querySelector('.case-col_wrapper'); const trigger = document.querySelector('.scroll-trigger'); const list = document.querySelector('.case-col-list'); const slides = list?.querySelectorAll('.case-slide'); const isMobile = window.innerWidth <= 768; if (!wrapper || !trigger || !list || !slides) { console.error('Required elements not found'); } else { if (isMobile) { wrapper.classList.add('swiper'); list.classList.add('swiper-wrapper'); slides.forEach(slide => slide.classList.add('swiper-slide')); const swiper = new Swiper('.case-col_wrapper', { slidesPerView: 1, spaceBetween: 8, freeMode: false, grabCursor: false, centeredSlides: false }); } else { function animateOnScroll() { const triggerRect = trigger.getBoundingClientRect(); const windowHeight = window.innerHeight; const start = windowHeight; const end = windowHeight - triggerRect.height; const scrollRange = start - end; const scrolled = start - triggerRect.top; let progress = scrolled / scrollRange; progress = Math.min(Math.max(progress, 0), 1); const vwInPx = window.innerWidth * 1.63; const listWidth = list.offsetWidth; const totalMove = vwInPx - listWidth; wrapper.style.transform = `translateX(-${progress * totalMove}px)`; } animateOnScroll(); window.addEventListener('scroll', animateOnScroll); window.addEventListener('resize', animateOnScroll); } } // 🌀 Marquee Scroll + ScrollTrigger Logic function initMarqueeScrollDirection() { // Clean up existing triggers and animations ScrollTrigger.getAll().forEach(trigger => trigger.kill()); gsap.globalTimeline.clear(); document.querySelectorAll('[data-marquee-scroll-direction-target]').forEach((marquee) => { const marqueeContent = marquee.querySelector('[data-marquee-collection-target]'); const marqueeScroll = marquee.querySelector('[data-marquee-scroll-target]'); if (!marqueeContent || !marqueeScroll) return; const { marqueeSpeed: speed, marqueeDirection: direction, marqueeDuplicate: duplicate, marqueeScrollSpeed: scrollSpeed } = marquee.dataset; const marqueeSpeedAttr = parseFloat(speed); const marqueeDirectionAttr = direction === 'right' ? 1 : -1; const duplicateAmount = parseInt(duplicate || 0); const scrollSpeedAttr = parseFloat(scrollSpeed); const speedMultiplier = window.innerWidth < 479 ? 0.25 : window.innerWidth < 991 ? 0.5 : 1; let marqueeSpeed = marqueeSpeedAttr * (marqueeContent.offsetWidth / window.innerWidth) * speedMultiplier; marqueeScroll.style.marginLeft = `${scrollSpeedAttr * -1}%`; marqueeScroll.style.width = `${(scrollSpeedAttr * 2) + 100}%`; if (duplicateAmount > 0) { const fragment = document.createDocumentFragment(); for (let i = 0; i < duplicateAmount; i++) { fragment.appendChild(marqueeContent.cloneNode(true)); } marqueeScroll.appendChild(fragment); } const marqueeItems = marquee.querySelectorAll('[data-marquee-collection-target]'); const animation = gsap.to(marqueeItems, { xPercent: -100, repeat: -1, duration: marqueeSpeed, ease: 'linear' }).totalProgress(0.5); gsap.set(marqueeItems, { xPercent: marqueeDirectionAttr === 1 ? 100 : -100 }); animation.timeScale(marqueeDirectionAttr); animation.play(); marquee.setAttribute('data-marquee-status', 'normal'); ScrollTrigger.create({ trigger: marquee, start: 'top bottom', end: 'bottom top', onUpdate: (self) => { const isInverted = self.direction === 1; const currentDirection = isInverted ? -marqueeDirectionAttr : marqueeDirectionAttr; animation.timeScale(currentDirection); marquee.setAttribute('data-marquee-status', isInverted ? 'normal' : 'inverted'); } }); const tl = gsap.timeline({ scrollTrigger: { trigger: marquee, start: '0% 100%', end: '100% 0%', scrub: 0 } }); const scrollStart = marqueeDirectionAttr === -1 ? scrollSpeedAttr : -scrollSpeedAttr; const scrollEnd = -scrollStart; tl.fromTo(marqueeScroll, { x: `${scrollStart}vw` }, { x: `${scrollEnd}vw`, ease: 'none' }); }); } initMarqueeScrollDirection(); // ✨ Button Hover Animation document.querySelectorAll('.button-text_wrap').forEach(wrap => { const first = wrap.querySelector('.button-text.first'); if (first && !wrap.querySelector('.button-text.second')) { const clone = first.cloneNode(true); clone.classList.remove('first'); clone.classList.add('second'); wrap.appendChild(clone); } }); // 📆 Footer Spots Availability Text const textElement = document.getElementById('availability-text'); if (textElement) { const today = new Date(); const currentDay = today.getDate(); const currentMonth = today.toLocaleString('nl-NL', { month: 'long' }).toLowerCase(); const currentYear = today.getFullYear(); const daysInMonth = new Date(currentYear, today.getMonth() + 1, 0).getDate(); const maxSpots = 5; const spotsLeft = Math.max(1, Math.ceil(((daysInMonth - currentDay + 1) / daysInMonth) * maxSpots)); const availabilityText = `We hebben nog ruimte voor ${spotsLeft} ${spotsLeft === 1 ? 'bedrijf' : 'bedrijven'} in ${currentMonth}!`; textElement.textContent = availabilityText; } // 💬 Tab inactive title change const documentTitleStore = document.title; const documentTitleOnBlur = "Hey, we missen je! 👀"; window.addEventListener("focus", () => { document.title = documentTitleStore; }); window.addEventListener("blur", () => { document.title = documentTitleOnBlur; }); function initMenuToggle() { const menu = document.querySelector('.menu-position'); const button = document.querySelector('.hamburger-button'); const navLinks = document.querySelectorAll('.nav-link'); if (!menu || !button) return; gsap.set(menu, { display: 'none', opacity: 0 }); let isOpen = false; function openMenu() { gsap.to(menu, { display: 'flex', opacity: 1, duration: 0.4, ease: 'power2.out' }); isOpen = true; } function closeMenu() { gsap.to(menu, { opacity: 0, duration: 0.4, ease: 'power2.in', onComplete: () => { gsap.set(menu, { display: 'none' }); } }); isOpen = false; } button.addEventListener('click', () => { isOpen ? closeMenu() : openMenu(); }); navLinks.forEach(link => { link.addEventListener('click', () => { if (isOpen) closeMenu(); }); }); } initMenuToggle(); }