canvas动态烟雾效果核心是粒子在流场中的物理启发式运动:用离屏canvas缓存粒子、主canvas半透明残影实现衰减,结合风场力+布朗运动更新粒子位置/大小/透明度,并通过柔边、运动模糊和lighter混合模式增强真实感。

用 Canvas 实现动态烟雾扩散效果,核心不是“画烟”,而是模拟粒子在流场中的运动与扩散——本质是基于物理启发的二维流体近似(如简化版的烟雾方程或粒子系统),配合 Canvas 2D 渲染的逐帧更新能力。关键在于:数据计算(CPU)和像素绘制(GPU)分离、利用 globalAlpha 和模糊叠加制造体积感、避免直接操作 imageData(性能瓶颈),而用多层 canvas + alpha 衰减 + 运动模糊来“骗”出烟雾感。
1. 构建基础 Canvas 结构与渲染循环
创建主画布用于显示,另配一个离屏 canvas(offscreenCanvas)作粒子缓冲层,提高重绘效率。使用 requestAnimationFrame 驱动平滑动画,每帧清空主 canvas 时保留一定透明度(模拟残影),而非完全清除:
- 设置主 canvas 背景为半透明黑色:
ctx.fillStyle = 'rgba(0,0,0,0.05)'; ctx.fillRect(0,0,width,height); - 离屏 canvas 用于绘制单帧粒子点(不透明),再以低透明度 drawImage 到主 canvas 上,形成自然衰减
- 避免
clearRect()全清,靠渐隐实现连续轨迹
2. 粒子系统模拟烟雾运动
不追求 Navier-Stokes 求解,用轻量级粒子+速度场方式:每个粒子带位置、速度、生命周期和大小;引入简化的“风向力场”(如鼠标位置为扰动源,产生径向排斥/吸引)和随机布朗运动分量:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 初始化 300–800 个粒子,初始位置集中在烟源区域(如底部中心)
- 每帧更新:速度 += 风场力 × dt + random(-0.1, 0.1);位置 += 速度 × dt;大小随生命周期线性缩小
- 用
ctx.beginPath(); ctx.arc(x,y,r,0,Math.PI*2); ctx.fill();绘制粒子,r 控制浓淡(大粒子更“浓”) - 粒子 alpha 值随生命周期从 1.0 降至 0,配合主 canvas 残影,形成弥散感
3. 添加视觉增强:软边与动态模糊
纯圆形粒子太生硬。通过两步提升真实感:
- 开启抗锯齿:
ctx.imageSmoothingEnabled = true;,并用ctx.shadowBlur = 8+shadowColor给粒子加柔边(比多次 draw 更快) - 模拟运动模糊:每帧绘制粒子时不只画当前点,按速度方向延伸画一条短透明线段(
lineTo(x+vx*0.5, y+vy*0.5)),粗细随速度变化 - 可选叠加一层高斯模糊滤镜(CSS
filter: blur(1px)在 canvas 外层容器上),但慎用——影响性能
4. 交互与优化技巧
让烟雾响应用户操作(如鼠标移动扰动气流),同时保障 60fps:
- 将风场预计算为二维数组(如 64×64 网格),每帧插值获取粒子受力,比实时计算距离快 10 倍
- 粒子超出画布边界或生命周期归零时,立即重置(对象池复用),避免频繁 new/delete
- 移动端禁用鼠标事件,改用 touchstart/touchmove 获取扰动源;添加
will-change: transform提示浏览器优化 - 用
ctx.globalCompositeOperation = 'lighter'替代多次叠加,让粒子交叠处自动增亮,模拟光散射
不需要 WebGL 或复杂库,纯 HTML5 Canvas 就能做出有呼吸感的烟雾。重点不在“画得多像”,而在“动得有多可信”——速度渐变、衰减节奏、边缘虚化这三点到位,人眼就会脑补出烟雾。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










