tsParticles Path Shape 实战指南:用 SVG 路径数据自定义粒子形状
【免费下载链接】tsparticlestsParticles - Easily create highly customizable JavaScript particles effects, confetti explosions and fireworks animations and use them as animated backgrounds for your website. Ready to use components available for React.js, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Inferno, Solid, Riot and Web Components.项目地址: https://gitcode.com/GitHub_Trending/ts/tsparticles
本指南围绕 tsParticles 官方路径形状扩展@tsparticles/shape-path展开,讲解如何通过 SVG 路径数据(move / line / bezier / quadratic / arc / ellipse 六种路径段)将粒子渲染为任意自定义轮廓,并将其应用于网页动态粒子背景。读完本文,你将掌握该扩展的安装方式(CDN、ESM、CommonJS)、loadPathShape的正确加载时序、particles.shape.options.path的完整配置结构,以及底层绘制原理与常见排错要点。
什么是 Path Shape
tsParticles 官方提供了大量内置形状(圆形、方形、星形等),而 Path Shape 是其中的一个扩展形状包:它允许你不写任何 Canvas 绘制代码,仅凭结构化的路径段数据(segments)就描述出任意的粒子轮廓。
在 shapes/path/package.json 中,该包被描述为 "tsParticles shape for rendering particles that follow SVG path data",其唯一运行时依赖是 @tsparticles/path-utils,后者负责把路径数据真正绘制到 Canvas 上。因此本文会同时介绍这两个包:@tsparticles/shape-path负责把「路径形状」注册进引擎,@tsparticles/path-utils负责底层几何绘制。
快速上手清单
按照官方 README 的 Quick checklist,接入只需三步:
- 安装
@tsparticles/engine(或直接引入下方的 CDN 包); - 在调用
tsParticles.load(...)之前调用包加载函数loadPathShape(...); - 在
tsParticles.load(...)的配置中使用particles.shape.type: "path"并填写particles.shape.options.path。
第 2 步的顺序至关重要,属于最常见的出错点:若先执行load后执行loadPathShape,引擎在解析配置时尚未注册 "path" 这一形状,粒子将无法按预期渲染(详见后文「常见误区」)。
安装与加载
CDN / Vanilla JS / jQuery
官方文档指出,CDN/Vanilla 版本只需引入一个必需文件:tsparticles.shape.path.min.js。引入后该文件会在全局导出加载函数:
loadPathShape之后即可异步设置 tsParticles 与形状:
(async () => { await loadPathShape(tsParticles); await tsParticles.load({ id: "tsparticles", options: { /* options */ /* here you can use particles.shape.type: "path" */ }, }); })();从源码看,浏览器入口 shapes/path/src/browser.ts 会把loadPathShape挂到全局对象上(globalObject.loadPathShape = loadPathShape),这就是 Vanilla 场景下全局函数名的来源。
ESM / CommonJS(npm 安装)
先安装包:
$ npm install @tsparticles/shape-path或:
$ yarn add @tsparticles/shape-pathCommonJS 方式:
const { tsParticles } = require("@tsparticles/engine"); const { loadPathShape } = require("@tsparticles/shape-path"); (async () => { await loadPathShape(tsParticles); })();ESM 方式:
import { tsParticles } from "@tsparticles/engine"; import { loadPathShape } from "@tsparticles/shape-path"; (async () => { await loadPathShape(tsParticles); })();包内loadPathShape的实现非常简洁(见 shapes/path/src/index.ts):
export async function loadPathShape(engine: Engine): Promise<void> { engine.checkVersion(__VERSION__); await engine.pluginManager.register(e => { e.pluginManager.addShape(["path"], () => Promise.resolve(new PathDrawer())); }); }它会先做引擎版本校验(checkVersion),再把PathDrawer以 "path" 为键注册进引擎的形状管理器。也就是说,配置里type既可以写字符串"path",也可以写数组(addShape接收的是数组,多个形状名可共用同一个 drawer)。此外包还提供了按需加载入口 shapes/path/src/index.lazy.ts,它通过动态import("./PathDrawer.js")实现懒加载,适合对首屏体积敏感的应用(对应 package.json 中的./lazy导出路径)。
配置项映射
官方 README 给出的映射关系如下:
- 主配置键:
particles.shape.type: "path" - 形状专属配置键:
particles.shape.options.path
最小配置骨架:
{ "particles": { "shape": { "type": "path", "options": { "path": {} } } } }注意shape.type是"path",而shape.options下对应的是"path"这个键(与形状名一致)。真正的路径数据就写在options.path中。
路径数据结构详解
options.path的数据结构定义在 utils/pathUtils/src/IPathData.ts:
export interface IPathSegmentData { type: SegmentType; values: ICoordinates[]; } export interface IPathData { half: boolean; segments: IPathSegmentData[]; }同时 shapes/path/src/IShapePathData.ts 将其与引擎的IShapeValues合并,作为粒子的形状数据:
export interface IShapePathData extends IShapeValues, IPathData {}其中IShapeValues(见 engine/src/Core/Interfaces/IShapeValues.ts)还提供了两个通用字段:close(路径是否闭合)与particles(形状级粒子选项覆盖),也就是说路径形状数据可以继续往下叠加自定义粒子选项。
segments:路径段数组
segments是一个路径段数组,每一段的type取自枚举 utils/pathUtils/src/SegmentType.ts,共六种:
| 类型 | 含义 | values 含义(均乘以粒子半径) |
|---|---|---|
move | 移动画笔(不画线) | 1 个点:目标坐标{x, y} |
line | 直线段 | 1 个点:线段终点{x, y} |
bezier | 三次贝塞尔曲线 | 4 个点:起点、两个控制点、终点 |
quadratic | 二次贝塞尔曲线 | 3 个点:起点、控制点、终点 |
arc | 圆弧 | 起始点 + 半径 + 起始角/结束角(弧度) |
ellipse | 椭圆弧 | 起始点 + 两个半径 + 旋转角 + 起止角 |
values中的坐标是相对坐标:在 utils/pathUtils/src/Utils.ts 的drawPath中,每个点都会被乘上粒子的radius(例如ctx.lineTo(value.x * radius, value.y * radius)),因此坐标写成 -1 ~ 1 之间的归一化值即可,粒子大小变化时形状自动缩放。
half:是否绘制镜像半边
half是布尔值。当half: true时,drawPath在画完正向路径后,会倒序遍历 segments,把点的 x 坐标取反(如ctx.lineTo(value.x * -radius, value.y * radius)),从而绘制出关于 Y 轴镜像的对称半边。从 Utils.ts 的源码看,该回程只支持line、bezier、quadratic三种段类型(arc与ellipse在镜像阶段被直接跳过)。因此:如果你想绘制左右对称的路径,half: true能自动补全另一半;若路径本身就不对称,或含圆弧/椭圆段,请保持half: false。
一个可运行的完整配置示例
仓库中的示例配置 utils/configs/src/s/shapePath.ts 给出了完整的实战用法。下面摘取其核心部分(已补全注释与默认值说明):
const options: ISourceOptions = { key: "shapePath", name: "Shape Path", particles: { number: { value: 80, density: { enable: true, }, }, paint: { fill: { color: { value: "#ff0000", animation: { enable: true, speed: 20, sync: true, }, }, enable: true, }, }, shape: { type: "path", options: { path: [ { segments: [ { type: "line", values: [{ x: -0.5, y: -0.5 }] }, { type: "bezier", values: [ { x: -0.5, y: 0.5 }, // 起点 { x: 1, y: 1 }, // 控制点 1 { x: 1, y: 0.5 }, // 控制点 2 { x: 1, y: -0.5 }, // 终点 ], }, { type: "quadratic", values: [ { x: 0.5, y: 0.5 }, // 起点 { x: 0.5, y: -0.5 }, // 控制点 { x: -0.5, y: 0.5 }, // 终点 ], }, { type: "line", values: [{ x: 0.5, y: -0.5 }] }, ], half: false, }, // 可继续定义第二个路径图形,粒子会随机从 options.path 数组中选取 ], }, }, opacity: { value: 0.5, }, size: { value: { min: 5, max: 50, }, }, move: { enable: true, speed: 6, direction: "none", }, }, background: { color: "#0d0d0d", }, };要点解读:
options.path是数组,可以同时定义多组路径,粒子会从数组中随机选用,适合做多形态混合效果;- 配合
paint(上色)、opacity、size、move等常规粒子选项即可组成完整的动画背景; - 所有路径坐标都在 -1 ~ 1 区间内归一化,配合
size.value的min/max控制粒子缩放范围。
绘制原理:PathDrawer 与 drawPath
Path Shape 的实现分为两层:
1. 形状注册层PathDrawer(shapes/path/src/PathDrawer.ts)实现引擎的IShapeDrawer接口:
particleInit:在粒子初始化时读取particle.shapeData,通过deepExtend({}, shape)深拷贝一份路径数据到particle.pathData,避免粒子间共享引用;draw:拿到context、particle、radius后,若particle.pathData存在则调用drawPath(context, radius, particle.pathData)完成绘制。
粒子类型PathParticle(见 shapes/path/src/PathParticle.ts)就是在标准Particle上追加了一个可选字段pathData?: IShapePathData。
2. 几何绘制层drawPath(utils/pathUtils/src/Utils.ts)按段类型映射到 Canvas 2D API:
| SegmentType | Canvas API |
|---|---|
move | ctx.moveTo(...) |
line | ctx.lineTo(...) |
bezier | ctx.bezierCurveTo(...) |
quadratic | ctx.quadraticCurveTo(...) |
arc | ctx.arc(...) |
ellipse | ctx.ellipse(...) |
实现细节值得注意:
- 每段
values[0]是该段的起点/操作点,缺失时该段会被continue跳过(容错处理); - 贝塞尔/圆弧段缺少必需的控制点或半径时也会跳过,因此构造配置时应保证各段 values 数量与类型匹配;
half: true的镜像回程实现参考前文「half 字段」一节。
与其他路径相关模块的关联
路径能力在 tsParticles 生态中并不止于粒子形状:
- 发射器路径形状:
@tsparticles/plugin-emitters-shape-path允许让粒子发射器(Emitter)沿着路径发射粒子。其实现 plugins/emittersShapes/path/src/EmittersPathShape.ts 把options.points中的百分比坐标(除以percentDenominator换算)构建成Path2D,并提供「路径周长上随机取点」与「路径内部随机取点」两种生成策略。如果你需要「粒子沿固定轨迹被发射」的效果,可查阅 plugins/emittersShapes/path/README.md,其加载函数为loadEmittersShapePathPlugin。 - 全量 bundle:
@tsparticles/all之类的聚合包会在初始化时自动调用loadPathShape(e)(见 bundles/all/src/index.lazy.ts),因此使用全量 bundle 时无需手动注册;只有按需引入单个包时,才需要遵循本文的加载顺序。
常见误区与排查建议
官方 README 专门列出了三条常见坑,结合源码补充说明如下:
- 在
loadPathShape(...)之前调用tsParticles.load(...):引擎解析配置时 "path" 形状尚未注册,会导致形状无法渲染。务必先await loadPathShape(tsParticles)再await tsParticles.load(...),并把两处await放在同一个异步流程中保证顺序。 - 启用高级选项前核对 peer 依赖:Path Shape 依赖
@tsparticles/path-utils(见 shapes/path/package.json 的dependencies),而引擎本身是 peer 依赖@tsparticles/engine。npm/yarn/pnpm 安装时若出现 peer 依赖缺失或版本不匹配,应优先解决依赖树问题;此外引擎有版本校验(engine.checkVersion),引擎与扩展版本差距过大时可能报版本错误。 - 一次只改一组选项:由于路径数据是 segments 数组,且
half、close、坐标归一化、各段 values 数量互相影响,建议每次只调整一个选项组(例如先只改segments,再改half,最后调paint/size),便于快速定位回归点。
小结
@tsparticles/shape-path用一套简洁的「段类型 + 相对坐标 + 镜像开关」数据模型,把自定义粒子形状的成本降到最低。你不需要写任何 Canvas 代码,只需要:
- 正确引入并先注册
loadPathShape; - 在
particles.shape.options.path中用segments描述形状(支持 move/line/bezier/quadratic/arc/ellipse); - 按需使用
half自动镜像、close闭合、particles子选项覆盖等能力。
如需深入学习底层绘制算法,可直接阅读 utils/pathUtils/src/Utils.ts 与 utils/pathUtils/src/SegmentType.ts;如需开箱即用的完整配置,可参考 utils/configs/src/s/shapePath.ts 中的Shape Path示例(80 个粒子、动态填充色、贝塞尔与二次曲线混合路径)。把路径数据与paint、move、size等选项组合,即可快速打造出形态独特、可无限扩展的粒子动画背景。
【免费下载链接】tsparticlestsParticles - Easily create highly customizable JavaScript particles effects, confetti explosions and fireworks animations and use them as animated backgrounds for your website. Ready to use components available for React.js, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Inferno, Solid, Riot and Web Components.项目地址: https://gitcode.com/GitHub_Trending/ts/tsparticles
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考