Files
haiguji-website-export/js/animations.js
T

122 lines
4.1 KiB
JavaScript

/**
* 首页动效编排
* - Lenis 平滑滚动
* - GSAP ScrollTrigger 驱动的分区揭示、扫描线签名效果
* - 首屏加载时的标题错落浮现
* - 产品卡片的 3D 悬浮跟随
*/
(function () {
var prefersReducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
/* ---------- 1. Lenis 平滑滚动 ---------- */
var lenis = null;
if (window.Lenis && !prefersReducedMotion) {
lenis = new Lenis({
duration: 1.15,
easing: function (t) { return Math.min(1, 1.001 - Math.pow(2, -10 * t)); },
smoothWheel: true,
wheelMultiplier: 1
});
if (window.gsap && window.ScrollTrigger) {
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add(function (time) {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
} else {
requestAnimationFrame(function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
});
}
}
/* ---------- 2. 首屏标题错落浮现 ---------- */
var revealItems = document.querySelectorAll('[data-reveal-item]');
if (window.gsap && revealItems.length) {
gsap.set(revealItems, { opacity: 0, y: 26 });
gsap.to(revealItems, {
opacity: 1,
y: 0,
duration: 0.9,
ease: 'power3.out',
stagger: 0.16,
delay: 0.3
});
}
if (!window.gsap || !window.ScrollTrigger) {
return; // 没有 GSAP 时,直接跳过滚动动效,保留静态可读的页面
}
gsap.registerPlugin(ScrollTrigger);
/* ---------- 3. 分区揭示 + 扫描线签名效果 ---------- */
document.querySelectorAll('.reveal-section').forEach(function (section) {
var revealTargets = section.querySelectorAll('.reveal-up');
var scanLine = section.querySelector('.section-scan');
if (revealTargets.length) {
gsap.set(revealTargets, { opacity: 0, y: 40 });
gsap.to(revealTargets, {
opacity: 1,
y: 0,
duration: 0.9,
ease: 'power3.out',
stagger: 0.14,
scrollTrigger: {
trigger: section,
start: 'top 78%',
once: true
}
});
}
});
/* ---------- 4. 产品卡片 3D 悬浮跟随 ---------- */
document.querySelectorAll('.tilt-card').forEach(function (card) {
var bounds;
card.addEventListener('mouseenter', function () {
bounds = card.getBoundingClientRect();
card.classList.add('is-tilting');
});
card.addEventListener('mousemove', function (e) {
if (!bounds) bounds = card.getBoundingClientRect();
var px = (e.clientX - bounds.left) / bounds.width - 0.5;
var py = (e.clientY - bounds.top) / bounds.height - 0.5;
gsap.to(card, {
rotateX: py * -8,
rotateY: px * 10,
duration: 0.4,
ease: 'power2.out',
transformPerspective: 700
});
});
card.addEventListener('mouseleave', function () {
card.classList.remove('is-tilting');
gsap.to(card, { rotateX: 0, rotateY: 0, duration: 0.6, ease: 'power3.out' });
});
});
/* ---------- 5. Hero logo 视差微动 ---------- */
var heroLogo = document.querySelector('.hero-brand-logo');
var hero = document.querySelector('.hero');
if (heroLogo && hero && !prefersReducedMotion) {
hero.addEventListener('mousemove', function (e) {
var rect = hero.getBoundingClientRect();
var px = (e.clientX - rect.left) / rect.width - 0.5;
var py = (e.clientY - rect.top) / rect.height - 0.5;
gsap.to(heroLogo, {
x: px * 14,
y: py * 10,
duration: 0.6,
ease: 'power2.out'
});
});
}
})();