烟雾背景特效(Canvas 烟雾粒子动画,浓度速度可调)

CANVASJS 许可:自研原创

烟雾背景特效:柔光烟雾粒子从底部缓缓升起,边升边摇曳边淡出,烟雾浓度、上升速度与不透明度实时可调,Canvas 自研并适配高分屏,复制即用。

效果演示(真实可交互)

烟雾粒子从画布底部持续生成,以随机速度向上漂浮,过程中按正弦轨迹左右摇曳,并经历”淡入-淡出”的完整生命周期,最后在顶部消散,像一缕缕青烟在深色背景上袅袅升起。三条滑杆分别控制烟雾浓度(每秒生成 1-20 个粒子)、上升速度(1-10)与不透明度(10%-90%)。关键细节是粒子颜色用径向渐变从中心到边缘透明,且透明度按 sin(π·life/maxLife) 变化——这是烟雾”由薄变浓再变淡”的自然感来源。每个粒子只保存位置、半径、相位等少量状态,生命周期结束后即被移除,内存占用恒定。

完整代码

<canvas id="smoke" style="width:100%;height:340px;display:block;background:linear-gradient(180deg,#131a2b,#0a0d18);"></canvas>
const canvas = document.getElementById('smoke');
const ctx = canvas.getContext('2d');
let W, H, parts = [], acc = 0;
const cfg = { density: 8, speed: 3, alpha: 45 };

function resize() {
  const r = canvas.getBoundingClientRect();
  const dpr = window.devicePixelRatio || 1;
  canvas.width = Math.round(r.width * dpr);
  canvas.height = Math.round(r.height * dpr);
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  W = r.width; H = r.height;
}
function spawn() {
  parts.push({
    x: Math.random() * W, y: H + 30,
    r: 24 + Math.random() * 42,               // 烟团半径
    speed: (Math.random() * .5 + .5) * cfg.speed,
    phase: Math.random() * Math.PI * 2,       // 摇曳相位
    sway: 14 + Math.random() * 26,            // 摇曳幅度
    life: 0, maxLife: 220 + Math.random() * 140,
  });
}
function step() {
  ctx.clearRect(0, 0, W, H);
  acc += cfg.density / 60;                    // 按帧累加生成
  while (acc >= 1) { spawn(); acc -= 1; }
  for (let i = parts.length - 1; i >= 0; i--) {
    const p = parts[i];
    p.life++;
    if (p.life > p.maxLife || p.y < -p.r * 2) { parts.splice(i, 1); continue; }
    p.y -= p.speed;
    p.x += Math.sin(p.phase + p.y * .01) * .5; // 摇曳
    const fade = Math.sin((p.life / p.maxLife) * Math.PI); // 淡入淡出
    const alpha = fade * (cfg.alpha / 100) * .5;
    const g = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r);
    g.addColorStop(0, `rgba(214, 222, 238, ${alpha})`);
    g.addColorStop(1, 'rgba(214, 222, 238, 0)');
    ctx.fillStyle = g;
    ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); ctx.fill();
  }
  requestAnimationFrame(step);
}
resize(); step();
window.addEventListener('resize', resize);

参数说明

参数位置说明
烟雾浓度cfg.density每秒生成粒子数 1-20
上升速度cfg.speed1-10,同时参与每粒子随机速度
不透明度cfg.alpha10-90,整体烟雾明暗
烟团半径24 + Math.random() * 42越大烟越”团”,越小越”丝”
摇曳幅度p.sway14-40,越大飘得越散
生命周期p.maxLife220-360 帧,越长烟升得越高

兼容性与性能

常见问题

Q: 为什么烟雾看起来像一个个圆圈而不是一片烟? 粒子密度不够或半径太小。提高浓度(10-15)、把半径下限调大(如 40),粒子之间相互重叠后就会连成连续的烟雾层。

Q: 能让烟雾颜色更”白”或更”彩”吗? 可以,把 rgba(214, 222, 238, ...) 换成任意颜色即可;暖色(如橙灰)适合烛火氛围,冷色适合科技感场景。

Q: 烟雾有时会突然消失是怎么回事? 每个粒子有 maxLife 生命周期,到期即被移除。若想让烟雾升得更高,加大 maxLife 或降低 p.speed,就能看到粒子飘到画面顶部。

Q: 可以和鼠标交互吗? 可以。在 mousemove 事件里对粒子施加斥力(参考本站萤火虫组件的驱散写法),就能做出”拨开烟雾”的效果。

许可与来源

  • 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
  • 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
  • 首次发布:2026-09-01 · 最近更新:2026-09-01
  • 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
  • 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理

常见问题

这个组件可以商用吗?

可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。

浏览器兼容性如何?

支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。

怎么修改动画参数?

直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。

✍️ 作者与审核