news 2026/9/17 11:42:38

tsParticles 粒子斥力交互插件 @tsparticles/interaction-particles-repulse:安装配置与源码级实现解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
tsParticles 粒子斥力交互插件 @tsparticles/interaction-particles-repulse:安装配置与源码级实现解析

tsParticles 粒子斥力交互插件 @tsparticles/interaction-particles-repulse:安装配置与源码级实现解析

【免费下载链接】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 仓库中的粒子间斥力(Repulse)交互插件展开:介绍@tsparticles/interaction-particles-repulse的安装与加载方式、particles.repulse配置项的完整用法,并结合仓库源码剖析Repulser交互器如何基于网格查询与距离衰减公式在每帧内驱动粒子相互排斥,读完后可独立完成该效果的接入与参数调优。

插件定位与快速接入清单

斥力交互插件是一个**粒子对粒子(particle-to-particle)**的自动交互:开启后,每个启用斥力的粒子会在其作用半径内"推开"其他粒子,无需鼠标等外部交互触发,常用于模拟流体感、气泡群、群体避让等动画背景。它属于 tsParticles 交互插件体系,依赖交互系统插件@tsparticles/plugin-interactivity提供的粒子交互调度机制(见 InteractionManager)。

按 README 的快速清单,接入只需三步:

  1. 安装@tsparticles/engine(或使用 CDN 版本);
  2. 在调用tsParticles.load(...)之前,先调用本包的加载函数(并先加载交互插件);
  3. tsParticles.load(...)options中应用本插件的选项键particles.repulse

接入方式一:CDN / Vanilla JS / jQuery

Vanilla 版本的 CDN 脚本中,斥力交互对应一个必需的 JS 文件:

tsparticles.interaction.particles.repulse.min.js

引入该文件后,它会导出一个用于加载交互插件的函数:

loadParticlesRepulseInteraction

脚本加载完成后的典型用法:

(async () => { await loadInteractivityPlugin(tsParticles); await loadParticlesRepulseInteraction(tsParticles); await tsParticles.load({ id: "tsparticles", options: {/* options */}, }); })();

注意执行顺序:loadInteractivityPlugin(tsParticles)必须先于tsParticles.load(...)完成。源码层面这一依赖是硬性校验的——插件注册时会调用ensureInteractivityPluginLoaded(e),在交互插件未加载的情况下抛出错误(见 index.ts)。

接入方式二:ESM / CommonJS

通过 npm 或 yarn 安装:

$ npm install @tsparticles/interaction-particles-repulse

$ yarn add @tsparticles/interaction-particles-repulse

CommonJS 引入方式:

const { tsParticles } = require("@tsparticles/engine"); const { loadInteractivityPlugin } = require("@tsparticles/plugin-interactivity"); const { loadParticlesRepulseInteraction } = require("@tsparticles/interaction-particles-repulse"); (async () => { await loadInteractivityPlugin(tsParticles); await loadParticlesRepulseInteraction(tsParticles); })();

ESM 引入方式:

import { tsParticles } from "@tsparticles/engine"; import { loadInteractivityPlugin } from "@tsparticles/plugin-interactivity"; import { loadParticlesRepulseInteraction } from "@tsparticles/interaction-particles-repulse"; (async () => { await loadInteractivityPlugin(tsParticles); await loadParticlesRepulseInteraction(tsParticles); })();

加载完成后可再调用tsParticles.load({...})传入选项配置。包名、版本与发布产物定义见 package.json。

插件注册流程:loadParticlesRepulseInteraction做了什么

阅读 index.ts 可以确认完整的注册链路:

export async function loadParticlesRepulseInteraction(engine: Engine): Promise<void> { engine.checkVersion(__VERSION__); await engine.pluginManager.register((e: InteractivityEngine) => { ensureInteractivityPluginLoaded(e); e.pluginManager.addInteractor?.("particlesRepulse", container => { return Promise.resolve(new Repulser(container)); }); }); }

关键点:

  • engine.checkVersion(__VERSION__):构建时注入的__VERSION__用于与当前引擎版本做兼容性校验;
  • ensureInteractivityPluginLoaded(e):校验@tsparticles/plugin-interactivity已注册,未注册则直接报错;
  • addInteractor("particlesRepulse", ...):向交互插件管理器注册一个名为particlesRepulse粒子交互器工厂,运行时由交互系统按容器(container)实例化出Repulser对象。

也就是说,本包本身不包含粒子渲染与帧循环逻辑,它只是向引擎的插件管理器"挂"了一个交互器,真正的每帧调度由交互系统统一驱动。

选项映射:particles.repulse完整配置

选项主键为particles.repulse(即Interactivity > Particles > repulse节点),最简开启配置:

{ "particles": { "repulse": { "enable": true } } }

完整字段说明以 官方选项文档 和选项类 ParticlesRepulse.ts 为准:

类型源码默认值说明
enablebooleanfalse是否启用斥力行为,关闭时交互器不会对该粒子生效
distancenumber/ range1斥力作用距离(半径),实际生效值会乘以视网膜像素比container.retina.pixelRatio
durationnumber/ range1文档中定义为效果持续时间(秒)
factornumber/ range1斥力强度系数,与speed相乘后构成作用速度
speednumber/ range1位移速度,越大粒子被推得越快、越远

除布尔开关外,distancedurationfactorspeed均为RangeValue类型,即除单一数值外还支持{ "min": x, "max": y }这样的区间随机取值形式,每个粒子的实际值会在区间内随机抽取(区间解析由getRangeValue完成)。选项类通过loadRangeProperty加载这些字段(见 ParticlesRepulse.ts)。

一个包含区间值的完整示例:

{ "repulse": { "enable": true, "distance": 120, "duration": 1.5, "factor": 1, "speed": 80, "value": { "min": 20, "max": 60 } } }

(示例中value区间写法沿用官方选项文档的演示,见 Repulse.md。从当前源码看,interact()实际参与位移计算的是distancespeedfactor三个区间值。)

源码级实现解析:Repulser交互器如何逐帧排斥粒子

核心逻辑全部位于 Repulser.ts。Repulser继承交互系统基类ParticlesInteractorBase,对外暴露四个关键方法。

生效条件:isEnabled

isEnabled(particle: RepulseParticle): boolean { return particle.options.repulse?.enabled ?? false; }

判定是逐粒子进行的:只有该粒子自身选项里repulse.enabledtrue时,它才会参与斥力交互。这意味着可以通过粒子组的差异化选项(如按颜色分组配置)让部分粒子带斥力、部分不带。

交互系统的调度入口在 InteractionManager:每帧粒子更新阶段,管理器遍历所有已注册的粒子交互器,对每个粒子依次调用isEnabled(particle)interact(particle, ...)。因此"粒子间自动交互"不需要任何鼠标事件驱动,属于interactParticle阶段内的自动行为。

作用半径初始化:视网膜适配与最大距离统计

interact()首次处理某粒子时会做一次性初始化(见 Repulser.ts):

p1.repulse = { distance: repulseDistance * container.retina.pixelRatio, speed: getRangeValue(repulseOpt1.speed), factor: getRangeValue(repulseOpt1.factor), };
  • 作用半径按pixelRatio放大,保证在 Retina/高分屏上"视觉上"的作用范围与配置值一致;
  • getRangeValue将区间配置解析为具体随机值,speedfactor各取一次;
  • 同时用if (repulseDistance > this.maxDistance)维护本容器的#maxDistance,供外部读取当前场景中最远的斥力半径。

排斥位移计算:网格查询 + 距离衰减

每帧对每个启用的粒子p1(见 Repulser.ts):

const pos1 = p1.getPosition(), query = container.particles.grid.queryCircle(pos1, p1.repulse.distance), p1DistanceFactor = identity / p1.repulse.distance; for (const p2 of query) { if (p1 === p2 || p2.destroyed) { continue; } const pos2 = p2.getPosition(), { dx, dy, distance } = getDistances(pos2, pos1), distanceFactor = identity / distance, velocity = p1.repulse.speed * p1.repulse.factor; if (distance > minDistance) { const repulseFactor = clamp((identity - Math.pow(distance * p1DistanceFactor, squareExp)) * velocity, minVelocity, velocity) * distanceFactor; this.#normVec.x = dx * repulseFactor; this.#normVec.y = dy * repulseFactor; p2.position.addTo(this.#normVec); } else { ... } }

可以拆解为四个要点:

  1. 空间索引加速container.particles.grid.queryCircle(pos1, distance)只取斥力半径内的候选粒子,避免 O(n²) 全量两两比较,这是大量粒子场景下斥力效果仍可实时的关键;
  2. 衰减曲线1 - (distance / maxDistance)²squareExp为平方指数)决定了"离得越近推得越狠"——距离趋近 0 时因子趋近 1,到达半径边缘时衰减为 0;
  3. 强度控制:位移速度velocity = speed × factor,最终再经clamp(..., minVelocity, velocity)限制在[minVelocity, velocity]区间,然后除以距离归一化方向向量(dx, dy)
  4. 位移作用对象:注意位移是加在对方粒子p2上的(p2.position.addTo(...)),即p1的斥力场把半径内其他粒子推开;当两者距离小于极小阈值minDistance时,退化为直接按velocity做轴向位移,防止除零和完全重合。

RepulseParticle类型(Repulser.ts)为每个粒子挂载了{ distance, factor, speed }的运行期缓存,初始化后不再重复解析区间值。另外从源码看,选项类中声明的duration字段在interact()的位移公式里并未被直接引用,当前实现的效果持续时间主要由粒子自身生命周期与后续帧的连续位移共同体现,调参时应以distance/speed/factor为主。

常见问题排查

以下问题在 README 的 Common pitfalls 中明确列出:

  • 调用顺序错误:在loadInteractivityPlugin(...)之前调用tsParticles.load(...)——斥力依赖交互系统的帧内调度,缺少它时particles.repulse配置不会生效;
  • 依赖包缺失:启用高级选项前先确认必需的 peer 包已安装(本插件要求@tsparticles/engine@tsparticles/plugin-interactivity);
  • 逐项排查法:一次只改一个选项组(比如只调distance),以便快速定位参数回归。

相关文件索引

文件作用
interactions/particles/repulse/README.md插件接入说明(CDN/ESM/CommonJS 与选项映射)
interactions/particles/repulse/src/index.ts插件加载函数与交互器注册
interactions/particles/repulse/src/Repulser.ts斥力交互器核心算法
interactions/particles/repulse/src/Options/Classes/ParticlesRepulse.ts选项类与默认值
interactions/particles/repulse/src/Options/Interfaces/IParticlesRepulse.ts选项接口定义
markdown/Options/Particles/Repulse.mdparticles.repulse字段表与示例
plugins/interactivity/src/InteractionManager.ts粒子交互器的每帧调度入口

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 11:38:43

SpringBoot+Vue网游推荐平台开发实战

1. 项目概述作为一名长期从事Java全栈开发的工程师&#xff0c;最近我完成了一个基于SpringBootVue的热门网游推荐平台项目。这个项目特别适合作为计算机相关专业的毕业设计或课程设计&#xff0c;因为它完整涵盖了现代Web开发的典型技术栈&#xff0c;包括后端API开发、前端交…

作者头像 李华
网站建设 2026/9/17 11:38:40

Win7镜像注入USB驱动:DISM离线注入FT232R/CP2104实战指南

1. 项目概述&#xff1a;为什么Win7原版镜像必须注入USB驱动&#xff1f;我做系统部署这行十多年&#xff0c;从XP时代一路折腾到Win11&#xff0c;但至今仍有大量工业控制设备、老旧医疗仪器、银行终端和学校机房在用Win7——不是不想升级&#xff0c;是硬件厂商早就不提供新系…

作者头像 李华
网站建设 2026/9/17 11:38:33

Claude Fable 5 中途回退到 Opus 4.8?TaoToken 这样改 Messages API 的请求

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华