HTML5 Canvas 粒子特效不能依赖 CSS 滤镜,需用 requestAnimationFrame 驱动 Canvas 2D API 手动更新绘制;粒子系统本质是数组管理对象,可用离屏 Canvas + shadowBlur + globalCompositeOperation 实现光晕效果,性能优化关键在于对象池复用。

HTML5 Canvas 里加粒子特效不是靠 CSS 滤镜
直接说结论:filter CSS 属性(比如 blur()、hue-rotate())对 Canvas 内容无效,除非你把整个 当成普通 DOM 元素去滤镜——但这滤的是最终渲染图层,不是粒子本身。真正在 Canvas 上做粒子动效,得自己算位置、颜色、生命周期,用 requestAnimationFrame 驱动,再用 ctx.drawImage() 或 ctx.fillRect() / ctx.beginPath() 一帧一帧画出来。
用 requestAnimationFrame + Canvas 2D API 实现基础粒子系统
粒子系统本质是数组管理:每个粒子是对象,含 x、y、vx、vy、life、size、color 等字段。主循环里更新+绘制,不依赖任何“滤镜”API。
- 每帧遍历粒子数组,更新坐标和生命值(
life--),移除life 的粒子 - 用
ctx.globalAlpha控制透明度,比反复改每个粒子 color 更快 - 画粒子优先用
ctx.fillRect(x, y, size, size)(矩形)或ctx.arc(x, y, radius, 0, Math.PI * 2)(圆形),避免频繁调用beginPath/stroke - 如果粒子量大(>1000),考虑用
Uint8ClampedArray直接操作ctx.getImageData().data,但开发成本高、调试难
想叠加模糊/光晕效果?用离屏 Canvas + globalCompositeOperation
Canvas 本身不提供“粒子发光模糊”,但可以用两层 Canvas 模拟:主层画粒子,副层(离屏)画带半透明的放大版粒子,再用 globalCompositeOperation = 'lighter' 叠加出光晕感。
- 创建离屏
canvas(document.createElement('canvas')),尺寸建议是屏幕的 1.5 倍,避免边缘裁剪 - 每次清空离屏 canvas 时用
ctx.clearRect(0,0,w,h),别用fillRect填黑——那会吃掉光晕叠加效果 - 在离屏 canvas 上画粒子时,
ctx.shadowBlur = 12+ctx.shadowColor = 'rgba(255,100,100,0.6)'能快速伪造柔边光斑 - 最后用
mainCtx.drawImage(offscreencanvas, 0, 0)合并,比逐个粒子加 shadow 性能好得多
WebGL 方案(Three.js)适合复杂粒子,但别为简单效果引入整套引擎
如果粒子要带旋转、透视、贴图、物理碰撞,或者数量上万,Canvas 2D 会卡顿。这时才该切到 WebGL:THREE.Points + THREE.PointsMaterial 是最轻量的入口。
立即学习“前端免费学习笔记(深入)”;
-
PointsMaterial.sizeAttenuation = true让粒子随距离自动缩放,模拟景深 - 用
vertexShader控制粒子运动逻辑,比 CPU 更新数组快一个数量级 - 但注意:
THREE.Sprite渲染的是带 alpha 的图片,而Points默认是纯色点——要发光效果还得配自定义 shader 或叠加 bloom 后处理(需EffectComposer) - 单纯想让 200 个飘动的小圆点带点余晖?Canvas 2D + 离屏 + shadowBlur 更快、更可控、无依赖
真正容易被忽略的点:粒子系统的性能瓶颈往往不在绘制,而在数组 push/splice 和对象创建。用对象池复用粒子实例,比每帧 new Particle() 省 30% 以上 GC 压力。










