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

使用AnimationFrames做滚动动画时如何清除旧帧避免拖影?

问题原因

  • 你遇到的拖影问题核心是每次绘制新帧前没有清空canvas画布上的旧内容,cancelAnimationFrame主要是用来避免滚动事件高频触发产生的冗余动画帧请求,不是清帧的核心方案。
  • 高频滚动时会触发多次requestAnimationFrame,未执行的请求堆积也可能导致画面更新错乱,所以也需要配套做rAF的去重处理。

修复后的完整代码

const canvas = document.getElementById("hero-lightpass");
const context = canvas.getContext("2d");

const frameCount = 148;
const currentFrame = index => (
  `images/1 & 2 Intro & Exploded View_${index.toString().padStart(5, '0')}.png`
)
// 存储requestAnimationFrame的id,用于取消冗余请求
let animationId = null;
// 预加载图片缓存,避免反复修改img.src可能出现的加载延迟
const imgCache = [];
const preloadImages = () => {
  for (let i = 1; i < frameCount; i++) {
    const img = new Image();
    img.src = currentFrame(i);
    imgCache[i] = img;
  }
};

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 => {
  // 先清空画布上的旧帧内容,这是解决拖影的核心步骤
  context.clearRect(0, 0, canvas.width, canvas.height);
  // 直接使用预加载的缓存图片,加载速度更快
  const targetImg = imgCache[index] || img;
  context.drawImage(targetImg, 0, 0);
}

window.addEventListener('scroll', () => {  
  const scrollTop = document.documentElement.scrollTop;
  const maxScrollTop = document.documentElement.scrollHeight - window.innerHeight;
  const scrollFraction = scrollTop / maxScrollTop;
  const frameIndex = Math.min(
    frameCount - 1,
    Math.ceil(scrollFraction * frameCount)
  );
  // 先取消之前还未执行的动画帧请求,避免冗余执行
  if (animationId) {
    cancelAnimationFrame(animationId);
  }
  animationId = requestAnimationFrame(() => updateImage(frameIndex + 1))
});

preloadImages()

关键修改说明

  1. 清画布逻辑:在updateImage绘制新帧前调用context.clearRect(0, 0, canvas.width, canvas.height),直接清除上一帧的所有内容,从根源解决拖影问题。
  2. rAF去重逻辑:新增变量存储requestAnimationFrame返回的ID,每次触发滚动事件时先调用cancelAnimationFrame取消上一次未执行的请求,避免高频滚动时的帧执行错乱。
  3. 优化图片加载:新增预加载图片缓存数组,绘制时直接取用缓存好的图片,避免反复修改img.src可能带来的加载延迟和闪烁问题。
  4. 修复变量缺失问题:原代码中直接使用的html变量未定义,替换为标准的document.documentElement获取滚动容器属性。

内容的提问来源于stack exchange,提问作者WoodyBRUH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:09:00