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

如何在类对象的window事件中正确切换requestAnimationFrame启停

问题根因

你的代码核心问题是没有对动画的运行状态做去重判断:

  • 滚动事件触发频率极高,只要滚动位置停留在1000-2000px区间内,每触发一次滚动就会调用一次requestAnimationFrame,生成的新动画ID会直接覆盖掉this.animID
  • 当滚动出区间时,cancelAnimationFrame只能终止最后一次生成的动画ID,之前生成的、已经进入循环的动画ID没有被终止,就会出现动画持续运行、内存泄漏导致浏览器卡顿的问题

修复代码

新增动画运行状态标记,避免重复启动动画,终止动画后重置状态和ID即可:

class MyClass {
  constructor() {
    this.updateAnim = this.updateAnim.bind(this);
    this.updateScroll = this.updateScroll.bind(this);
    this.animID = null;
    // 新增动画运行状态标记
    this.isAnimRunning = false;
  }

  updateAnim() {
    // do stuff
    console.log("update anim");

    // continue loop
    this.animID = requestAnimationFrame(this.updateAnim);
  }

  updateScroll() {
    console.log("scrolling");
    const scrollY = window.scrollY;

    if (scrollY > 1000 && scrollY < 2000) {
      // 只有动画没在运行的时候才启动,避免重复生成动画ID
      if (!this.isAnimRunning) {
        this.animID = requestAnimationFrame(this.updateAnim);
        this.isAnimRunning = true;
        console.log("anim on");
      }
    } else {
      // 只有动画在运行的时候才终止
      if (this.isAnimRunning) {
        cancelAnimationFrame(this.animID);
        // 重置状态和ID
        this.animID = null;
        this.isAnimRunning = false;
        console.log("anim off");
      }
    }
  }

  init() {
    window.addEventListener("scroll", this.updateScroll);
  }
}

如果你的需求需要刚好覆盖1000和2000的边界,把判断条件改成scrollY >= 1000 && scrollY <= 2000即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:30:04