You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

滚动帧动画优化求助:增加单滚动帧数与添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:43:16