feat: story-journey immersive layer (progress, scene focus, floating orbs)
All checks were successful
Deploy / deploy (push) Successful in 2s
All checks were successful
Deploy / deploy (push) Successful in 2s
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
// ═══ 星空粒子系统 ═══
|
||||
const canvas = document.getElementById('starfield');
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
let width, height, stars, nebulas;
|
||||
let animationId;
|
||||
@@ -133,6 +134,55 @@
|
||||
});
|
||||
}
|
||||
|
||||
// ═══ 场景滚动进度 + 旅程节点高亮 ═══
|
||||
function setupStoryJourney() {
|
||||
const body = document.getElementById('storyBody');
|
||||
const progress = document.getElementById('storyProgress');
|
||||
if (!body || !progress) return;
|
||||
|
||||
const scenes = Array.from(body.querySelectorAll(':scope > p'));
|
||||
if (!scenes.length) return;
|
||||
|
||||
const onScroll = () => {
|
||||
const rect = body.getBoundingClientRect();
|
||||
const total = Math.max(body.scrollHeight - window.innerHeight, 1);
|
||||
const scrolled = Math.min(Math.max(-rect.top, 0), total);
|
||||
const ratio = scrolled / total;
|
||||
progress.style.width = `${(ratio * 100).toFixed(2)}%`;
|
||||
|
||||
let activeIndex = 0;
|
||||
let minDistance = Infinity;
|
||||
scenes.forEach((p, idx) => {
|
||||
const r = p.getBoundingClientRect();
|
||||
const d = Math.abs(r.top - window.innerHeight * 0.35);
|
||||
if (d < minDistance) {
|
||||
minDistance = d;
|
||||
activeIndex = idx;
|
||||
}
|
||||
});
|
||||
scenes.forEach((p, idx) => p.classList.toggle('active-scene', idx === activeIndex));
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
onScroll();
|
||||
}
|
||||
|
||||
// ═══ 漂浮光团轻微视差 ═══
|
||||
function setupOrbsParallax() {
|
||||
const orbs = document.querySelectorAll('.story-orb');
|
||||
if (!orbs.length) return;
|
||||
|
||||
window.addEventListener('scroll', () => {
|
||||
const y = window.scrollY;
|
||||
orbs.forEach((orb, i) => {
|
||||
const factor = (i + 1) * 0.04;
|
||||
const xShift = Math.sin(y * 0.002 + i) * 10;
|
||||
const yShift = y * factor;
|
||||
orb.style.transform = `translate(${xShift}px, ${yShift}px)`;
|
||||
});
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// ═══ 初始化 ═══
|
||||
window.addEventListener('resize', () => {
|
||||
resize();
|
||||
@@ -146,6 +196,8 @@
|
||||
setupReveal();
|
||||
setupParallax();
|
||||
setupGlow();
|
||||
setupStoryJourney();
|
||||
setupOrbsParallax();
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user