tsParticles EmittersShapes 插件详解:用 5 种发射器形状精确控制粒子生成区域
【免费下载链接】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 中,emitters(发射器)负责按时间节奏持续生成粒子,而粒子究竟从哪里冒出来,则由发射器的**形状(shape)**决定。plugins/emittersShapes/目录下的 5 个独立插件为发射器补充了canvas、circle、path、polygon、square五种开箱即用的形状实现——从最简单的矩形/圆形区域,到用任意 HTML Canvas 内容(图片、文本、现有画布)逐像素决定发射点的高级玩法。阅读本文后,你将掌握每种形状的安装方式、emitters.shape.type与对应选项的完整配置方法,以及其背后的随机取点算法原理,可直接在自己的粒子效果中落地使用。
一、EmittersShapes 插件是什么
plugins/emittersShapes/下的一组插件是 tsParticles 发射器系统(Emitters 插件文档)的形状扩展。它们不定义任何顶层(top-level)的 options 配置节,而是通过向发射器注册IEmitterShapeGenerator实现,让你在emitters.shape.type中按名称选用形状。
这种设计意味着:形状是发射器的一个属性,而不是独立的配置项。你只需要在启动粒子引擎前注册对应的形状插件,然后按下面的结构配置即可:
{ "emitters": { "shape": { "type": "circle", "options": {} } } }其中type填写形状名(如"circle"、"path"),options传入该形状专有的配置(不同形状见下文各小节)。
二、5 种发射器形状一览
| 包名(package) | 形状名(type) | 说明 |
|---|---|---|
@tsparticles/plugin-emitter-shape-canvas | canvas | 以 HTML Canvas 内容(图片、文本、现有画布)为发射区域,逐像素随机取点 |
@tsparticles/plugin-emitter-shape-circle | circle | 圆形发射区域 |
@tsparticles/plugin-emitter-shape-path | path | 基于 SVG Path 折线路径的发射区域 |
@tsparticles/plugin-emitter-shape-polygon | polygon | 多边形发射区域(可配置边数与旋转角) |
@tsparticles/plugin-emitter-shape-square | square | 正方形/矩形发射区域(发射器默认形状) |
每个包在仓库中对应plugins/emittersShapes/<shape>/目录,遵循统一的源码组织方式,例如 circle 形状的核心实现位于 EmittersCircleShape.ts,生成器位于 EmittersCircleShapeGenerator.ts。生成器实现IEmitterShapeGenerator.generate(),由发射器在初始化时调用,返回具体的形状实例——这是所有形状插件统一的接入机制。
三、square:发射器默认的矩形区域
square是发射器的默认形状(在 Emitters.md 中EmitterShape默认值为{ "type": "square", "options": {} }),因此在不显式配置形状时,粒子默认从矩形区域内生成。
该形状无需任何 options。它的行为受发射器的两个基础属性影响:
fill: true(默认):粒子在矩形内部随机生成。从 EmittersSquareShape.ts 的randomPosition()可见,内部取点使用position + offset * (getRandom() - 0.5),即在 x/y 两个维度上均匀随机分布。fill: false:粒子只在矩形的四条边上生成。实现中通过getRandomSize(4)随机选中上/右/下/左(Sides枚举)一条边,再在该边上随机取点(见 EmittersSquareShape.ts)。
{ "emitters": { "shape": { "type": "square" }, "size": { "width": 40, "height": 10, "mode": "percent" }, "fill": true, "rate": { "quantity": 2, "delay": 0.1 } } }四、circle:圆形与圆环发射区域
circle形状通过极坐标随机取点。核心实现在 EmittersCircleShape.ts:
- 以椭圆方程计算当前随机角度对应的最大半径
radius = (a*b) / sqrt((b*cosθ)² + (a*sinθ)²),其中a、b分别为宽高的一半; fill: true时,半径取maxRadius * sqrt(getRandom()),使用sqrt保证整圆面积上的概率密度均匀(否则圆心附近会聚集过多粒子);fill: false时,半径直接取maxRadius,粒子只会出现在圆周上。
注意:该实现同时支持宽高不等的椭圆发射区域。最小配置示例如下:
{ "emitters": { "shape": { "type": "circle" }, "position": { "x": 50, "y": 30 }, "size": { "width": 20, "height": 20, "mode": "percent" }, "rate": { "quantity": 3, "delay": 0.2 } } }五、polygon:可旋转的多边形发射区域
polygon形状生成一个正多边形作为发射区域,配置项定义在 EmittersPolygonShapeOptions.ts:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
sides | number | 5 | 多边形边数(如 5 = 五边形,3 = 三角形,6 = 六边形) |
angle | number | 0 | 多边形整体旋转角(度,内部通过degToRad转为弧度) |
在 EmittersPolygonShape.ts 中,多边形顶点由generateRandomPolygon()基于发射器位置、size.width / 2半径与旋转角计算得出;fill: true时在内部取点(generateRandomPointWithinPolygon),fill: false时在多边形周长上取点(generateRandomPointOnPolygonPerimeter)。顶点算法与取点工具位于 utils.ts。
{ "emitters": { "shape": { "type": "polygon", "options": { "sides": 6, "angle": 15 } }, "position": { "x": 50, "y": 50 }, "size": { "width": 30, "height": 30, "mode": "percent" }, "fill": false } }六、path:用折线路径定义发射区域
path形状用一系列百分比坐标点(折线)来描绘发射区域轮廓,配置项定义在 EmittersPathShapeOptions.ts:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
points | ICoordinates[] | [] | 定义路径的坐标点数组,坐标为百分比(0–100),缺省单项时回退为{ x: 50, y: 50 } |
在 EmittersPathShape.ts 中,每个百分比坐标会被换算为实际像素坐标(offset + point * size / 100),并用Path2D依次moveTo/lineTo首尾闭合;发射器resize时会重新计算路径。取点时:
fill: true:generateRandomPointWithinPath()在路径内部取点;fill: false:generateRandomPointOnPathPerimeter()在路径周长上取点。
两点取点算法均依赖离屏 Canvas 的isPointInPath判断,实现在 utils.ts。一个五角星形路径的示例:
{ "emitters": { "shape": { "type": "path", "options": { "points": [ { "x": 50, "y": 0 }, { "x": 61, "y": 35 }, { "x": 98, "y": 35 }, { "x": 68, "y": 57 }, { "x": 79, "y": 91 }, { "x": 50, "y": 70 }, { "x": 21, "y": 91 }, { "x": 32, "y": 57 }, { "x": 2, "y": 35 }, { "x": 39, "y": 35 } ] } }, "rate": { "quantity": 5, "delay": 0.1 } } }七、canvas:把任意画面变成发射区域(图片/文本/现有画布)
canvas是功能最丰富的形状:它把一张图片、一段文本或一个现有的 HTML Canvas 渲染为像素数据,然后只在不透明像素处随机生成粒子,从而让粒子效果“临摹”任意图形。其选项定义在 EmittersCanvasShapeOptions.ts,完整参数如下:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
element | HTMLCanvasElement | undefined | 直接传入一个 Canvas 元素作为像素来源 |
selector | string | "" | CSS 选择器,用于从 DOM 中查找 Canvas 元素 |
image | HTMLImageElement | undefined | 图片元素(使用其src加载绘制) |
text | TextOptions | 见下方子选项 | 以文本作为像素来源 |
pixels | PixelsOptions | { offset: 4 } | 像素采样步长(offset),值越大发射点越稀疏、性能越好 |
scale | number | 1 | 形状的缩放系数,用于放大/缩小发射区域 |
filter | string \| ((pixel: IRgba) => boolean) | pixel => pixel.a > 0 | 像素过滤函数,决定哪些像素允许生成粒子 |
在 EmittersCanvasShape.ts 的init()中,四种来源按优先级依次尝试:
image:通过getImageData(url, offset, renderSettings)异步加载图片并采样像素;element或selector:取到 Canvas 后通过getCanvasImageData()读取其 2D 上下文像素;text:通过getTextData()先把文本按指定字体渲染到离屏画布再采样(来自@tsparticles/canvas-utils)。
randomPosition()(EmittersCanvasShape.ts)在width * height的像素网格中随机选点,用filter(pixel)判断该像素是否“可用”(默认仅要求 alpha > 0),最多重试maxRetries = 100次;命中后按scale换算为实际坐标,并返回该像素的颜色与透明度——这意味着发射出的粒子还能自动带上图形本身的颜色(color: { ...pixel }、opacity: pixel.a)。
7.1 用文本作为发射区域
text子选项(TextOptions.ts)包含:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
color | string | "#000000" | 绘制文本的颜色 |
text | string | "" | 要绘制的文本内容 |
font.family | string | "Verdana" | 字体族(TextFontOptions.ts) |
font.size | string \| number | 32 | 字号 |
font.style | string | "" | 字体样式(如"italic") |
font.variant | string | "" | 字体变体(如"small-caps") |
font.weight | string | "" | 字重(如"bold") |
lines.separator | string | "\n" | 多行文本的分隔符(TextLinesOptions.ts) |
lines.spacing | number | 0 | 行间距(像素) |
文本形状配置示例:
{ "emitters": { "shape": { "type": "canvas", "options": { "text": { "text": "Hi!", "color": "#ffffff", "font": { "family": "Arial", "size": 64, "weight": "bold" }, "lines": { "spacing": 4 } }, "pixels": { "offset": 6 }, "scale": 1.2 } }, "rate": { "quantity": 8, "delay": 0.05 } } }7.2 用现有 Canvas 元素或图片作为发射区域
如果页面上已有一个画布(例如用脚本画出的 Logo 或图形),可用selector或element直接引用;也可以传入一个图片元素:
{ "emitters": { "shape": { "type": "canvas", "options": { "selector": "#myCanvas", "pixels": { "offset": 2 }, "filter": "myPixelFilter" } } } }filter的用法值得注意:在 EmittersCanvasShape.ts 中,如果传入字符串,实现会去globalThis(即window)上查找同名函数并用作过滤回调,因此你可以把过滤逻辑写成全局函数:
window.myPixelFilter = (pixel) => pixel.r > 200 && pixel.a > 0;也可以用内联函数(TS/JS 配置)实现同样的效果,例如只让偏红的像素发射粒子。
八、如何在项目中接入使用
8.1 安装与注册
这些形状插件都是独立的 npm 包,与@tsparticles/plugin-emitters配合使用。以 circle 为例:
npm install @tsparticles/plugin-emitter-shape-circle然后在初始化时通过initParticlesEngine注册(各包均提供 ESM 与懒加载入口,见各包src/index.ts与src/index.lazy.ts):
import { initParticlesEngine } from "@tsparticles/engine"; import { loadEmittersPlugin } from "@tsparticles/plugin-emitters"; import { loadEmittersShapeCircle } from "@tsparticles/plugin-emitter-shape-circle"; await initParticlesEngine(async (engine) => { await loadEmittersPlugin(engine); await loadEmittersShapeCircle(engine); });提示:由于形状通过
emitters.shape.type名称解析,注册哪个包就启用哪种形状;未注册的形状名将无法解析,请确保注册与配置一一对应。完整的发射器选项(position、size、rate、life、particles等)参见 Emitters 插件文档。
8.2 与fill属性的配合
fill是控制所有形状行为方式的通用开关(默认true):
fill: true:粒子在形状内部生成;fill: false:粒子只在形状的轮廓/边界上生成。
它对五种形状全部生效:square 只在四条边上、circle 只在圆周上、polygon 只在周长上、path 只在路径轮廓上、canvas 则只取通过filter的像素点。设计“描边式”或“空心式”发射效果时,优先利用这个属性而不是调整size。
九、实现原理小结:统一的形状抽象
从源码结构看,所有形状插件都遵循同一套抽象(@tsparticles/plugin-emitters中的IEmitterShapeGenerator/EmitterShapeBase):
- Generator 注册:每个插件导出
loadEmittersShapeXxx(engine),向引擎注册生成器,供emitters.shape.type按名解析; - 形状实例化:
generate()接收容器、位置、尺寸、fill与选项,构造形状实例; init():异步准备形状数据(canvas 形状在此采样像素;其余形状为空实现);randomPosition():每次生成粒子时调用,返回一个随机坐标(canvas 形状额外返回颜色与透明度);resize():容器尺寸变化时重建几何(path、polygon 实现了重建逻辑)。
理解这条调用链后,如果需要自定义全新形状,也可以参考任一插件的目录结构(circle 包是最简参考实现)自行扩展。
结语
EmittersShapes 系列插件把“从哪里发射粒子”从固定矩形扩展为圆形、多边形、SVG 路径乃至任意图片/文本像素区域,配合fill开关即可自由组合出喷泉、圆环、图形描边、像素文字等丰富的发射形态。只需按本文所述注册对应插件并在emitters.shape.type中选用形状,再对照各形状的options微调参数,即可在 tsParticles 中实现高度可控的粒子发射区域。
【免费下载链接】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),仅供参考