最快路径是直接用tsparticles,5分钟内上线可交互粒子背景;它基于canvas但已封装动画循环、鼠标交互、响应式适配和性能节流,兼容性好、文档清晰。

直接用 tsparticles 是最快路径,5 分钟内上线可交互粒子背景;自己手写 Canvas 粒子系统虽灵活,但调试成本高、易卡顿,除非你明确需要定制物理逻辑或图像驱动粒子。
用 tsparticles 快速初始化粒子背景
这是目前最省力、兼容性好、文档清晰的方案。它基于 Canvas,但封装了动画循环、鼠标交互、响应式适配和性能节流逻辑。
- 在 HTML 中引入脚本:
<script src="https://cdn.jsdelivr.net/npm/tsparticles@3.2.0/tsparticles.min.js"></script> - 加一个容器:
<div id="tsparticles" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: -1;"></div>(注意z-index: -1防止遮挡内容) - 初始化时调用
particlesLoad,传入配置对象(不是 JSON 字符串):particlesLoad("tsparticles", { particles: { number: { value: 80 }, color: { value: "#6a5acd" }, shape: { type: "circle" }, opacity: { value: 0.7 }, size: { value: 3 } }, interactivity: { events: { onhover: { enable: true, mode: "repulse" } } } }); - 别漏掉 CSS 重置:
canvas { display: block; },否则部分浏览器下 canvas 会自带底部空白
Canvas 手写粒子:为什么 init() 里要重设 canvas.width/height
因为 canvas.width 和 canvas.height 是绘图缓冲区尺寸,不是 CSS 样式尺寸。只改 CSS 会让画布被拉伸模糊,而缓冲区仍按旧尺寸渲染——粒子运动轨迹、碰撞检测、鼠标坐标映射全错。
- 必须在
window.resize和初始化时同步设置:canvas.width = window.innerWidth; canvas.height = window.innerHeight; - 如果容器非全屏,应读取父元素
getBoundingClientRect(),而非window尺寸 -
ctx.scale(devicePixelRatio, devicePixelRatio)可提升高清屏显示质量,但需同步缩放鼠标坐标
鼠标交互失效?检查这三个地方
粒子跟随/排斥鼠标是高频需求,但常因坐标映射错误或事件绑定时机不对而“不动”。
- Canvas 绑定的是
mousemove,但获取的clientX/clientY是视口坐标,需减去 canvas 的getBoundingClientRect().left/top才是画布内坐标 - 若 canvas 使用
position: fixed或transform,getBoundingClientRect()仍有效,但不要手动加 scroll 偏移——它已包含滚动位置 - 粒子更新逻辑里,距离计算要用欧氏距离平方(
dx*dx + dy*dy),避免开方运算拖慢帧率
粒子连线上不了线?globalCompositeOperation 搞错了
连线效果本质是多条线段叠加后的视觉混合,不是简单画线。默认 "source-over" 模式下,后画的线会盖住前画的,看不出“光迹感”。
- 想实现发光连接线,应在绘制连线前设:
ctx.globalCompositeOperation = "lighter"; - 画完连线后记得切回:
ctx.globalCompositeOperation = "source-over";,否则后续粒子会被异常叠加 - 如果用了离屏 canvas 做光晕层,主 canvas 上 drawImage 时也需确保
globalCompositeOperation是默认值
真正难的不是让点动起来,而是让它们动得自然、不抢内容焦点、不卡低端机——粒子数量超过 200 就该考虑用 requestIdleCallback 节流更新,或把生命周期管理从数组 splice 改为对象池复用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











