Canvas烟花动画卡顿掉帧主因是未用requestAnimationFrame;须用其递归驱动、避免耗时计算、限制粒子数并复用粒子池;需每帧更新粒子位置与生命周期;用lighter混合模式替代阴影实现光晕;canvas宽高须设属性值而非仅CSS。
绝大多数卡顿问题根源就在这里——用 setTimeout 或 setInterval 驱动动画,帧率不受控,还容易和浏览器刷新节奏错开。Canvas 动画必须用 requestAnimationFrame,它会自动对齐屏幕刷新率(通常是 60fps),且在标签页不可见时暂停执行,省资源。
实操建议:
立即学习“前端免费学习笔记(深入)”;
function animate() { /* 清空、更新、绘制 */ requestAnimationFrame(animate); }
animate 里做耗时计算(比如大量粒子坐标重算),可提前缓存物理参数或用固定步长简化运动模型这是初学者最常漏的一步:只画了初始爆炸效果,但没在每一帧中持续更新每个粒子的 vx、vy 和 x、y。Canvas 是“一次性绘图”,不会自动记住上一帧状态。
实操建议:
立即学习“前端免费学习笔记(深入)”;
{ x, y, vx, vy, radius, alpha, life };life 控制存活帧数或透明度衰减particle.x += particle.vx; particle.y += particle.vy; particle.vy += 0.05; // 模拟重力
particles = particles.filter(p => p.life > 0),否则数组无限膨胀拖慢 JS 执行原生 Canvas 默认是“覆盖”模式(globalCompositeOperation = 'source-over'),多层亮色粒子叠在一起就变脏。真实烟花需要“叠加发光”效果,靠的是混合模式或模糊阴影。
实操建议:
立即学习“前端免费学习笔记(深入)”;
ctx.globalCompositeOperation = 'lighter'(Chrome/Firefox 支持,Safari 16+ 也支持),让亮色自动叠加增强亮度ctx.shadowBlur,它开销大;统一用 lighter 混合 + 渐变色填充更高效常见原因是 canvas 元素没设宽高(只靠 CSS 缩放),导致 getBoundingClientRect() 返回的坐标和 clientX/clientY 不匹配,计算出的点击位置偏移。
实操建议:
立即学习“前端免费学习笔记(深入)”;
width 和 height 属性必须显式设置为整数(如 <canvas width="800" height="600">),不能只靠 CSSconst rect = canvas.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top;
rect.width / canvas.width 校正比例复杂点往往藏在坐标校准和生命周期管理里,而不是数学公式本身。粒子一多,filter 和 forEach 的性能差异立刻显现,别等卡了才回头改结构。