如何在类对象的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
相关产品推荐
相关产品推荐

