AvantscapeAI's picture
Initial DeepSite commit
8f36b23 verified
Raw
History Blame Contribute Delete
4.71 kB
// Icons
lucide.createIcons();
// GSAP
gsap.registerPlugin(ScrollTrigger);
// Nav glass on scroll
const navbar = document.getElementById('navbar');
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
navbar.classList.add('nav-glass');
} else {
navbar.classList.remove('nav-glass');
}
});
// Mobile menu
const menuBtn = document.getElementById('menuBtn');
const closeMenu = document.getElementById('closeMenu');
const mobileMenu = document.getElementById('mobileMenu');
const mobileLinks = document.querySelectorAll('.mobile-link');
function toggleMenu(show) {
if (show) {
mobileMenu.classList.remove('opacity-0', 'pointer-events-none');
document.body.style.overflow = 'hidden';
} else {
mobileMenu.classList.add('opacity-0', 'pointer-events-none');
document.body.style.overflow = '';
}
}
menuBtn.addEventListener('click', () => toggleMenu(true));
closeMenu.addEventListener('click', () => toggleMenu(false));
mobileLinks.forEach(link => link.addEventListener('click', () => toggleMenu(false)));
// Hero auto-morph
const morphCard = document.getElementById('morphCard');
const morphImg = document.getElementById('morphImg');
const morphOverlays = document.getElementById('morphOverlays');
const morphGlow = document.getElementById('morphGlow');
const heroTl = gsap.timeline({ delay: 1 });
heroTl
.to(morphCard, {
rotateY: -8,
rotateX: 6,
scale: 0.96,
borderRadius: '32px',
duration: 1.8,
ease: 'power3.out'
})
.to(morphImg, {
scale: 1.2,
duration: 2.2,
ease: 'power2.out'
}, '<')
.to(morphOverlays, {
opacity: 1,
duration: 1,
ease: 'power2.out'
}, '-=1.8')
.to(morphGlow, {
opacity: 1,
duration: 2,
ease: 'power2.out'
}, '<');
// Hero float loop
gsap.to(morphCard, {
y: -8,
rotateY: -4,
rotateX: 3,
duration: 4,
repeat: -1,
yoyo: true,
ease: 'sine.inOut',
delay: 3
});
// Process steps highlight
const steps = document.querySelectorAll('.process-step');
steps.forEach((step, index) => {
ScrollTrigger.create({
trigger: step,
start: 'top 70%',
end: 'bottom 30%',
onEnter: () => updateSteps(index),
onEnterBack: () => updateSteps(index)
});
});
function updateSteps(activeIndex) {
steps.forEach((s, i) => {
if (i <= activeIndex) {
s.classList.remove('opacity-30');
s.classList.add('opacity-100');
} else {
s.classList.add('opacity-30');
s.classList.remove('opacity-100');
}
});
}
// Scroll morph image zoom + chrome reveal
gsap.to('#scrollMorphImg', {
scale: 1.25,
ease: 'none',
scrollTrigger: {
trigger: '#scrollMorphContainer',
start: 'top 80%',
end: 'bottom 20%',
scrub: true
}
});
gsap.to('#scrollMorphChrome', {
opacity: 1,
ease: 'none',
scrollTrigger: {
trigger: '#scrollMorphContainer',
start: 'top 60%',
end: 'center center',
scrub: true
}
});
gsap.to('#scrollProgress', {
width: '100%',
ease: 'none',
scrollTrigger: {
trigger: '#scrollMorphContainer',
start: 'top 60%',
end: 'bottom 20%',
scrub: true
}
});
// Before / After slider
const baSlider = document.getElementById('baSlider');
const baHandle = document.getElementById('baHandle');
const baBeforeLayer = document.getElementById('baBeforeLayer');
let isDragging = false;
function updateBA(x) {
const rect = baSlider.getBoundingClientRect();
let percentage = ((x - rect.left) / rect.width) * 100;
percentage = Math.max(0, Math.min(100, percentage));
baHandle.style.left = percentage + '%';
baBeforeLayer.style.clipPath = `inset(0 ${100 - percentage}% 0 0)`;
}
baHandle.addEventListener('mousedown', () => isDragging = true);
window.addEventListener('mouseup', () => isDragging = false);
window.addEventListener('mousemove', (e) => {
if (!isDragging) return;
updateBA(e.clientX);
});
baHandle.addEventListener('touchstart', () => isDragging = true, { passive: true });
window.addEventListener('touchend', () => isDragging = false);
window.addEventListener('touchmove', (e) => {
if (!isDragging) return;
updateBA(e.touches[0].clientX);
}, { passive: true });
baSlider.addEventListener('click', (e) => {
if (e.target.closest('#baHandle')) return;
updateBA(e.clientX);
});
// Entrance reveals
const revealSections = document.querySelectorAll('section');
revealSections.forEach((section) => {
const targets = section.querySelectorAll('h1, h2, h3, p, .group, .process-step, .ba-slider');
gsap.from(targets, {
y: 30,
opacity: 0,
duration: 0.8,
stagger: 0.08,
ease: 'power2.out',
scrollTrigger: {
trigger: section,
start: 'top 85%',
toggleActions: 'play none none reverse'
}
});
});