JS Canvas柱状图动画实现是否正确 运行速度是否与设备分辨率无关
前端Canvas动画问题解答
附原实现代码
const canvas = document.querySelector('canvas'); const ctx = canvas.getContext('2d'); canvas.width = window.innerHeight / 3 * 4; canvas.height = window.innerHeight; const xCharCnt = window.innerHeight / 3 * 4 / 48; const yCharCnt = window.innerHeight / 34; const foreground1 = "#AF5BEC"; let offset = 0; const barHeight = 20; const speed = 4; const limit = yCharCnt * barHeight; let requestId = window.requestAnimationFrame(render); function render() { requestId = window.requestAnimationFrame(render); // Clear screen ctx.clearRect(0, 0, canvas.width, canvas.height); // Draw bar ctx.fillStyle = foreground1; ctx.fillRect(xCharCnt * 7, yCharCnt * 28, xCharCnt, -offset); offset = offset + speed; // Cancel animation if (offset >= limit) window.cancelAnimationFrame(requestId); }
问题a:上述代码的动画实现方式是否为正确的前端动画实现方案?
是符合前端Canvas动画规范的正确实现,理由如下:
- 采用
requestAnimationFrame驱动动画,而非setTimeout/setInterval,该API会和浏览器刷新频率同步执行,避免无效渲染,页面切后台时会自动暂停,性能更优 - 每帧渲染前主动清空画布再绘制新内容,逻辑链路通顺
- 动画结束后主动调用
cancelAnimationFrame销毁 pending 状态的回调,避免不必要的性能损耗和内存泄漏
唯一可以优化的小细节:可以把requestAnimationFrame(render)的调用放到render函数的末尾,提前终止逻辑可以少执行一次无用的回调注册,不过不影响整体正确性。
问题b:无论运行设备的分辨率是多少,该动画是否始终保持相同的运行速度?
不会,动画速度会受屏幕刷新率、设备分辨率两个因素影响:
- 受屏幕刷新率影响:
requestAnimationFrame的触发频率和屏幕刷新率完全匹配,60Hz屏幕每秒触发60次回调,144Hz屏幕每秒触发144次。代码中每次回调固定给offset加4,刷新率越高offset增长越快,高刷屏上动画会明显更快结束 - 受设备分辨率/窗口尺寸影响:动画结束的阈值
limit = yCharCnt * barHeight,而yCharCnt和window.innerHeight直接挂钩,窗口越高limit越大,就算刷新率完全一致,要完成的offset总增长量更大,动画总时长也会更长。
如果要实现多设备下速度一致,可以改成基于时间差计算offset增量,或者固定动画总时长用进度百分比计算offset即可。
内容的提问来源于stack exchange,提问作者MightyA
相关产品推荐
相关产品推荐

