萤火虫背景特效(Canvas 萤火虫动画,鼠标驱散互动)

CANVASJS 许可:自研原创

萤火虫背景特效:发光的萤火虫在深色夜空随机游走、呼吸闪烁,鼠标划过会被驱散,数量、飞行速度、光晕大小实时可调,Canvas 自研适配高分屏。

效果演示(真实可交互)

一群萤火虫在深蓝夜空里缓缓游荡,每只都带有独立的呼吸式闪烁节奏:亮度按正弦曲线在 30%-95% 之间起伏,光晕半径也随之微微伸缩,营造出忽明忽暗的生命感。把鼠标移进画面,附近的萤火虫会被一股”斥力”推开,划过一片便散开一片,离开画布后它们又慢慢聚回。演示面板可以调整萤火虫数量(10-80)、飞行速度(1-10)与光晕大小(8-30px)。运动模型采用”随机游走 + 限速”:每帧给速度叠加一个微小的随机扰动再钳制到上限,让轨迹平滑又不可预测,比直线往返自然得多。

鼠标划过,萤火虫会被驱散 🪲

完整代码

<canvas id="firefly" style="width:100%;height:340px;display:block;background:radial-gradient(120% 120% at 50% 0%,#0d1b2e,#04070d);"></canvas>
const canvas = document.getElementById('firefly');
const ctx = canvas.getContext('2d');
let W, H, flies = [];
const cfg = { count: 35, speed: 3, glow: 16 };
const mouse = { x: -9999, y: -9999 };

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() {
  return {
    x: Math.random() * W, y: Math.random() * H,
    vx: (Math.random() - .5) * cfg.speed, vy: (Math.random() - .5) * cfg.speed,
    phase: Math.random() * Math.PI * 2, tw: Math.random() * Math.PI * 2,
  };
}
function init() { flies = []; for (let i = 0; i < cfg.count; i++) flies.push(spawn()); }

function step() {
  ctx.clearRect(0, 0, W, H);
  for (const f of flies) {
    // 随机游走 + 限速
    f.phase += .01;
    f.vx += (Math.random() - .5) * .2;
    f.vy += (Math.random() - .5) * .2;
    const sp = Math.hypot(f.vx, f.vy) || 1;
    if (sp > cfg.speed) { f.vx = f.vx / sp * cfg.speed; f.vy = f.vy / sp * cfg.speed; }
    // 鼠标驱赶:120px 内施加斥力
    const dx = f.x - mouse.x, dy = f.y - mouse.y;
    const dm = Math.hypot(dx, dy);
    if (dm < 120 && dm > .01) {
      const force = (120 - dm) / 120 * 1.6;
      f.vx += dx / dm * force; f.vy += dy / dm * force;
    }
    f.x += f.vx; f.y += f.vy;
    if (f.x < 0 || f.x > W) f.vx *= -1;
    if (f.y < 0 || f.y > H) f.vy *= -1;
    // 呼吸闪烁 + 径向渐变光晕
    f.tw += .04;
    const alpha = .3 + .65 * (Math.sin(f.tw) * .5 + .5);
    const r = cfg.glow * (.6 + .8 * Math.sin(f.tw));
    const g = ctx.createRadialGradient(f.x, f.y, 0, f.x, f.y, r);
    g.addColorStop(0, `rgba(255,236,130,${alpha})`);
    g.addColorStop(.35, `rgba(255,210,90,${alpha * .45})`);
    g.addColorStop(1, 'rgba(255,210,90,0)');
    ctx.fillStyle = g;
    ctx.beginPath(); ctx.arc(f.x, f.y, r, 0, Math.PI * 2); ctx.fill();
  }
  requestAnimationFrame(step);
}
resize(); init(); step();
window.addEventListener('resize', () => { resize(); init(); });

canvas.addEventListener('mousemove', e => {
  const r = canvas.getBoundingClientRect();
  mouse.x = e.clientX - r.left; mouse.y = e.clientY - r.top;
});
canvas.addEventListener('mouseleave', () => { mouse.x = -9999; mouse.y = -9999; });

参数说明

参数位置说明
萤火虫数量cfg.count10-80,越多画面越热闹,性能开销线性增长
飞行速度cfg.speed1-10,同时作为速度上限
光晕大小cfg.glow8-30px,实际光晕在其 60%-140% 间呼吸
闪烁频率f.tw += .04调大闪得更快
驱散半径dm < 120鼠标影响范围,可调大增强互动感
光色渐变三档颜色可整体换成冷色调(青蓝)或暖色调

兼容性与性能

常见问题

Q: 为什么萤火虫经常扎堆在角落? 边界用的是速度反向(反弹),如果随机游走扰动太大,粒子会贴着边界滑动。可以把反弹改为”推回中心方向”,或在边界处增加随机逃逸速度。

Q: 光晕太亮/太暗怎么调? 亮度由 alpha 公式 0.3 + 0.65*(sin+1)/2 决定,把 0.65 换成 0.4 会更内敛;光晕半径则由 cfg.glow 控制。

Q: 想加入点击”吸引”效果? 把驱散逻辑的斥力方向取反即可变成吸引力:f.vx -= dx / dm * force,就能做出萤火虫飞向鼠标的效果。

Q: 性能比粒子系统差吗? 不会。这里每只萤火虫只有位置、速度、相位三个状态,无碰撞计算,O(n) 复杂度,比带连线计算的粒子系统便宜得多。

许可与来源

  • 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
  • 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
  • 首次发布: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(缓动曲线)等属性即可,代码中有注释说明。

✍️ 作者与审核