Chrome浏览器在滚动时,HTML画布会卡顿

前端开发 2026-07-09

这里的代码基本上展示自上一次绘制帧以来经过了多久,当dt > 20ms时就会变成红色。

通常我的电脑可以让requestAnimationFrame以 60fps(约16ms)运行,但当我滚动时,它会闪出红色并且卡顿很严重。

<!DOCTYPE html>
<html>
<style>
  body, html {
  overflow: hidden;
  overscroll-behavior: none;
}
</style>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, maximum-scale=1, minimum-scale=1, viewport-fit=cover">
</head>
<body style="padding:0;margin:0;background-color: #151515;pointer-events: none">
<script>

class LCanvas{ 
  constructor(){
    this.canvas = document.createElement("canvas")
    this.ctx = this.canvas.getContext("2d")
    this.canvas.style.position = "fixed"
    this.canvas.style.top = "0px"
    this.canvas.style.left = "0px"
    this.canvas.style.pointerEvents = "none"
    document.body.appendChild(this.canvas)
    return(this)
  }

  fitScreenSize(){
    this.canvas.width = window.innerWidth
    this.canvas.height = window.innerHeight
  }

  clear(){
    this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)
  }
}

var can = new LCanvas()
can.clear()
can.fitScreenSize()
var lastTime = 0

function mainLoop(){
  requestAnimationFrame(mainLoop)
  let now = performance.now()
  let dt = now-lastTime
  lastTime = now
  can.clear()
  can.ctx.font = "40px arial"
  can.ctx.fillStyle = dt>20?"red":"pink"
  can.ctx.fillText(dt,100,100)
  can.ctx.fillRect(400,100,dt*50,100)

}
requestAnimationFrame(mainLoop,true)


</script>

</body>
</html>

在这段极短的视频中,当我的光标放在页面底部附近时向下滚动
https://www.youtube.com/watch?v=da2YuPcyNvc

滚动时,它清楚地会闪出红色,并把帧率从60fps变到90fps。其实并不需要滚得这么快,滚轮一个小小的刻度就足以出现红色条。

这里每一帧的绘制性能其实并不是瓶颈。我可以绘制成千上万的东西,它本应一直流畅,直到我触碰滚轮,才会卡顿几帧。

如果改用setInterval而不是requestAnimationFrame,问题就不会再出现。

我在Firefox上也试过,也没有这个问题。Chrome有没有解决办法?

解决方案

添加这一行就能修复滚动时的卡顿
document.addEventListener("wheel",(e)=>{e.preventDefault()},{passive: false})

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章