tsParticles Emitters Shape Circle 插件完全指南:从安装配置到圆形发射区算法原理
【免费下载链接】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/plugin-emitters-shape-circle(仓库路径 plugins/emittersShapes/circle),系统讲解它的安装方式、加载顺序、配置入口与底层实现原理。读完本文,你将掌握如何在tsParticles.load(...)中配置圆形/椭圆发射区域,理解fill、size、shape.type等参数如何影响粒子生成,并能从源码层面看懂圆形发射区随机采样(拒绝采样式椭圆均匀分布)的数学实现,直接应用于烟火、喷泉、泡泡等自定义粒子特效场景。
插件是什么:给 Emitters 增加 circle 发射区形状
tsParticles 的 Emitters 插件(@tsparticles/plugin-emitters)允许你在画布中定义"发射器"——一块持续或按频率产生粒子的区域。发射器的形状决定了粒子从怎样的几何区域中出生:默认内置square形状,而 plugins/emittersShapes/circle 这个插件则补充了circle(圆形/椭圆形)发射区。
它的本质是一个极小的注册型插件:不引入新的顶级配置键,而是向 Emitters 的形状管理器注册一个名为"circle"的 shape generator。注册之后,你在emitter.shape.type: "circle"时即可触发圆形发射逻辑。
从源码结构看,该插件由 4 个核心文件组成:
- EmittersCircleShape.ts —— 圆形发射区形状类,实现随机出生点算法;
- EmittersCircleShapeGenerator.ts —— 形状工厂,负责实例化
EmittersCircleShape; - index.ts —— 加载入口,导出
loadEmittersShapeCircle加载函数; - index.lazy.ts —— 懒加载(lazy)变体入口,按需动态 import。
安装与加载:必须遵守的先后顺序
与所有 tsParticles 插件一样,正确使用本插件有严格的三步走:
- 安装(或通过 CDN 引入)
@tsparticles/engine与@tsparticles/plugin-emitters; - 在调用
tsParticles.load(...)之前,先调用插件的加载函数; - 在
tsParticles.load(...)的 options 配置中应用对应参数。
CDN / Vanilla JS / jQuery 方式
在浏览器中通过 CDN 引入tsparticles.plugin.emitters.shape.circle.min.js文件后,全局会暴露loadEmittersShapeCircle函数:
(async () => { await loadEmittersPlugin(tsParticles); await loadEmittersShapeCirclePlugin(tsParticles); await tsParticles.load({ id: "tsparticles", options: {/* options */}, }); })();注意原文档给出的函数名为loadEmittersShapeCirclePlugin;在当前仓库源码中,browser.ts 实际导出的全局函数为loadEmittersShapeCircle(index.ts 中导出的加载函数名),二者所指相同,以当前源码导出名为准。
ESM / CommonJS 方式
先安装包(package 名来自 package.json 的name字段):
$ npm install @tsparticles/plugin-emitters-shape-circle或使用 yarn:
$ yarn add @tsparticles/plugin-emitters-shape-circleCommonJS 引入方式:
const { tsParticles } = require("@tsparticles/engine"); const { loadEmittersPlugin } = require("@tsparticles/plugin-emitters"); const { loadEmittersShapeCirclePlugin } = require("@tsparticles/plugin-emitters-shape-circle"); (async () => { await loadEmittersPlugin(tsParticles); await loadEmittersShapeCirclePlugin(tsParticles); })();ESM 引入方式:
import { tsParticles } from "@tsparticles/engine"; import { loadEmittersPlugin } from "@tsparticles/plugin-emitters"; import { loadEmittersShapeCirclePlugin } from "@tsparticles/plugin-emitters-shape-circle"; (async () => { await loadEmittersPlugin(tsParticles); await loadEmittersShapeCirclePlugin(tsParticles); })();无论哪种模块方式,加载顺序都不可颠倒:必须先加载@tsparticles/plugin-emitters,再加载本形状插件。原因在源码中一目了然——index.ts 的注册回调里调用了ensureEmittersPluginLoaded(e),而该函数(见 ensureEmittersPluginLoaded.ts)会在 emitters 插件未加载时直接抛出错误"tsParticles Emitters Plugin is not loaded"。此外engine.checkVersion(__VERSION__)还会校验引擎与插件的版本兼容性。
懒加载(Lazy)入口
如果你关心首屏包体,可以使用@tsparticles/plugin-emitters-shape-circle/lazy子路径(见 package.json 的 exports 配置)。对应的 index.lazy.ts 会通过await import(...)动态加载@tsparticles/plugin-emitters/lazy与形状生成器,把插件代码拆成独立 chunk,仅在运行时需要时才拉取。
配置入口:emitter.shape.type: "circle"
本插件不引入独立的顶层 options 键,而是直接挂载在 Emitters 插件的既有配置结构之下。完整的发射器配置形如:
await tsParticles.load({ id: "tsparticles", options: { emitters: { position: { x: 50, y: 50 }, // 发射器中心位置(百分比) size: { width: 40, height: 30, mode: "percent" }, // 发射区宽高 fill: true, // 粒子出生在区域内(false 则只从边缘出生) shape: { type: "circle", // 关键:使用圆形发射区 options: {}, // 圆形状暂无额外选项 replace: { color: false, opacity: false }, }, rate: { quantity: 1, delay: 0.1 }, }, }, });关键配置项的语义与来源:
| 配置项 | 类型 | 默认值 | 说明 | 源码依据 |
|---|---|---|---|---|
emitter.shape.type | string | "square" | 发射区形状类型;插件注册后可使用"circle" | EmitterShape.ts |
emitter.shape.options | Record<string, unknown> | {} | 形状专属选项,圆形状无需额外参数 | EmitterShape.ts |
emitter.shape.replace | {color, opacity} | false/false | 是否用形状填充色/透明度覆盖出生粒子的颜色/透明度 | EmitterShapeReplace.ts |
emitter.fill | boolean | true | true时粒子在整个圆/椭圆内部出生;false时只在圆周/椭圆周出生 | Emitter.ts |
emitter.size | {width, height, mode} | 0/0/percent | 发射区宽高;mode支持percent(相对画布百分比)或precise(像素) | EmitterSize.ts |
emitter.position | {x, y} | — | 发射器中心坐标(与 size 的 mode 对应) | Emitter.ts |
关于shape.options:从 EmitterShape.ts 的load实现可以看到,options会通过deepExtend深合并进 shape 配置;而本插件的EmittersCircleShape构造函数接收options后并未使用它(见 EmittersCircleShape.ts),因此圆形发射区目前没有专属形状参数。
size的mode字段需要注意:EmitterSize.ts 中默认是PixelMode.percent,即宽高按画布百分比计算。width与height的比值决定了发射区是正圆还是椭圆:两者相等为正圆,不等则为椭圆。
底层原理:圆形发射区的随机出生点是如何计算的
当配置了shape.type: "circle"后,EmitterInstance.ts 会通过emitterShapeManager.getShapeGenerator(shapeOptions.type)找到已注册的 circle generator,并调用其generate(...)创建形状实例;每次发射粒子时再调用this.#shape.randomPosition()获取随机出生点(见 EmitterInstance.ts)。
EmittersCircleShapeGenerator.generate()(EmittersCircleShapeGenerator.ts)的作用很单纯:把 container、position、size、fill、options 原样传入,构造EmittersCircleShape实例。
真正的算法核心在 EmittersCircleShape.ts 的randomPosition()中,它解决了一个关键问题:在椭圆内部均匀随机取点。如果直接用"随机角度 + 随机半径"的极坐标方式,会在椭圆中心聚集过多粒子(密度不均匀)。该实现的做法是:
- 取半轴长:
[a, b] = [size.width * half, size.height * half],即椭圆的两个半轴; - 均匀生成角度 θ:
generateTheta(x, y)使用u = getRandom() * quarter(quarter即 1/4,对应 90°),通过theta = Math.atan((y / x) * Math.tan(doublePI * u))计算第一象限角度,再依据随机变量v的四个区间把 θ 映射到四个象限(θ、π−θ、π+θ、−θ),从而在[0, 2π)上均匀分布。这里利用了"椭圆上角度均匀分布 ⇔ 对应辅助圆参数角均匀分布"的数学性质; - 计算该角度下的椭圆半径:
radius(x, y, θ) = (x·y) / sqrt((y·cos θ)² + (x·sin θ)²),即椭圆在角度 θ 方向上的边界半径(squareExp即指数 2); - 按 fill 决定径向距离:
randomRadius = fill ? maxRadius * Math.sqrt(getRandom()) : maxRadius。- 当
fill: true时,半径乘以sqrt(getRandom())——由于面积正比于 r²,对 r² 均匀采样等价于对面积均匀采样,从而保证粒子在圆/椭圆内部面积均匀分布(中心不会堆积); - 当
fill: false时,randomRadius恒等于maxRadius,所有粒子只落在圆周/椭圆周上。
- 当
最终出生点坐标为position + randomRadius * (cos θ, sin θ),叠加到发射器中心位置之上。
EmittersCircleShape继承自 EmitterShapeBase(@tsparticles/plugin-emitters提供的抽象基类),基类负责统一管理position、size、fill、options四个字段,并提供resize()供容器尺寸变化时同步更新发射区;子类只需实现init()(此处为空实现,见 EmittersCircleShape.ts)和randomPosition()。
常见坑位排查
原文档给出了三条实战提醒,结合源码可进一步展开:
- 在
tsParticles.load(...)之前必须完成插件加载。因为EmitterInstance创建时会立即用shape.type查询形状生成器(EmitterInstance.ts),若circle尚未注册,查询结果为undefined,#shape不会创建,后续randomPosition()也不会执行——发射器会退化为使用this.position单点发射(见 EmitterInstance.ts),表现上就是"没有圆形区域效果"。 - 确认 peer 依赖已就绪。本插件的 package.json 声明
@tsparticles/engine与@tsparticles/plugin-emitters为 peerDependencies,缺失或版本不匹配会触发ensureEmittersPluginLoaded的报错或checkVersion的版本校验失败。 - 一次只改动一个配置组。
fill、size.mode、shape.type、rate相互独立又共同影响粒子出生表现,逐项调整便于快速定位回归原因。
扩展阅读
- 形状注册与查询的基础设施:ShapeManager.ts(内部用
Map<string, IEmitterShapeGenerator>管理全部形状生成器)、addEmittersShapesManager.ts(向 engine 挂载addEmitterShapeGenerator方法)、EmittersEngine.ts(扩展后的引擎类型); - 发射器完整配置项:Emitter.ts、IEmitter.ts;
- 形状选项加载逻辑:EmitterShape.ts 与 EmitterShapeReplace.ts;
- 其他发射器形状实现可参考仓库
plugins/emittersShapes/目录下的其他子包,结构与本插件一致。
【免费下载链接】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),仅供参考