滚动帧动画优化求助:增加单滚动帧数与添加Fadeout效果
滚动帧动画优化实现
优化需求解决
1. 实现单次滚动过程中切换更多动画帧
原代码通过Math.ceil计算帧索引易导致跳帧,改为线性映射帧索引,让滚动进度与帧序列完全对应,确保每段滚动都触发帧切换,提升动画细腻度:
- 将帧索引计算逻辑从
Math.ceil(scrollFraction * frameCount)调整为Math.floor(scrollFraction * (frameCount - 1)),实现滚动进度到帧索引的平滑映射。 - 修复预加载逻辑,确保全部148帧都被预加载(原代码遗漏最后一帧)。
2. 添加Fadeout淡出效果
通过Canvas的globalAlpha属性控制图像透明度,设置滚动进度阈值(80%),当滚动超过阈值后逐渐降低透明度,直到滚动结束时完全淡出:
- 在
updateImage函数中根据滚动进度计算实时透明度值。 - 绘制图像前先清除画布,设置透明度完成绘制后再重置,避免影响后续操作。
修改后的完整代码
JavaScript
const html = document.documentElement; const canvas = document.getElementById("hero-lightpass"); const context = canvas.getContext("2d"); const frameCount = 148; const currentFrame = index => ( `https://www.apple.com/105/media/us/airpods-pro/2019/1299e2f5_9206_4470_b28e_08307a42f19b/anim/sequence/large/01-hero-lightpass/${index.toString().padStart(4, '0')}.jpg` ) // 修复预加载:覆盖全部148帧 const preloadImages = () => { for (let i = 1; i <= frameCount; i++) { const img = new Image(); img.src = currentFrame(i); } }; const img = new Image() img.src = currentFrame(1); canvas.width = 1158; canvas.height = 770; img.onload = function() { context.drawImage(img, 0, 0); } // 新增透明度计算逻辑,接收滚动进度参数 const updateImage = (index, scrollFraction) => { const fadeThreshold = 0.8; // 滚动到80%时开始淡出 let alpha = 1; // 超过阈值后线性降低透明度至0 if (scrollFraction > fadeThreshold) { alpha = Math.max(0, 1 - ((scrollFraction - fadeThreshold) / (1 - fadeThreshold))); } img.src = currentFrame(index + 1); context.clearRect(0, 0, canvas.width, canvas.height); context.globalAlpha = alpha; context.drawImage(img, 0, 0); context.globalAlpha = 1; // 重置透明度 } window.addEventListener('scroll', () => { const scrollTop = html.scrollTop; const maxScrollTop = html.scrollHeight - window.innerHeight; const scrollFraction = scrollTop / maxScrollTop; // 线性映射帧索引,避免跳帧 const frameIndex = Math.floor(scrollFraction * (frameCount - 1)); requestAnimationFrame(() => updateImage(frameIndex, scrollFraction)) }); preloadImages()
CSS
html { height: 100vh; } body { height: 500vh; background: #000; } canvas { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); max-width: 100vw; max-height: 100vh; }
HTML
<canvas id="hero-lightpass" />
内容的提问来源于stack exchange,提问作者MihanN1
相关产品推荐
相关产品推荐

