:构建粒子间互相吸引效果的完整实践)
tsParticles 粒子吸引交互插件tsparticles/interaction-particles-attract构建粒子间互相吸引效果的完整实践【免费下载链接】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本文基于当前仓库中interactions/particles/attract包的官方 README 与源码实现讲解 tsParticles 的“粒子间吸引”交互插件如何通过 CDN 或 ESM/CommonJS 方式安装并注册loadParticlesAttractInteraction如何配置particles.attract选项组以及Attractor类在每一帧中如何借助空间网格查询与反向速度修正让彼此靠近的粒子产生相互牵引的物理效果。插件定位与快速检查清单该包是 tsParticles 的一个粒子交互Particles Interaction插件专门负责粒子与粒子之间的吸引效果。它与“外部交互”如鼠标 repulse/attract 鼠标附近的粒子不同吸引力的施加对象是场景内的其他粒子两个粒子会各自朝对方方向被拉动形成成对靠近、聚合或环绕的视觉动效。官方 READMEinteractions/particles/attract/README.md给出的启用检查清单只有三步这也是本仓库所有交互插件包的标准启用模式安装tsparticles/engine或使用 CDN 打包文件在调用tsParticles.load(...)之前调用插件的加载函数loader在tsParticles.load(...)的配置中写入本包的选项particles.attract。安装与注册CDN / Vanilla / jQuery 方式README 说明Vanilla/CDN 场景下只需要引入一个 JS 文件tsparticles.interaction.particles.attract.min.js它导出加载该交互插件的函数loadParticlesAttractInteraction;脚本加载完成后注册插件并启动容器的标准写法如下与 README 中的 Usage 示例一致(async () { await loadInteractivityPlugin(tsParticles); await loadParticlesAttractInteraction(tsParticles); await tsParticles.load({ id: tsparticles, options: {/* options */}, }); })();这里loadInteractivityPlugin(tsParticles)必须先于或至少同时加载Attractor本身继承自 interactivity 插件提供的交互器基类缺少 interactivity 插件时粒子交互管线不会建立。安装与注册ESM / CommonJS 方式通过包管理器安装$ npm install tsparticles/interaction-particles-attract或$ yarn add tsparticles/interaction-particles-attract然后在应用中导入并注册。README 同时给出了 CommonJS 与 ESM 两种写法const { tsParticles } require(tsparticles/engine); const { loadInteractivityPlugin } require(tsparticles/plugin-interactivity); const { loadParticlesAttractInteraction } require(tsparticles/interaction-particles-attract); (async () { await loadInteractivityPlugin(tsParticles); await loadParticlesAttractInteraction(tsParticles); })();import { tsParticles } from tsparticles/engine; import { loadInteractivityPlugin } from tsparticles/plugin-interactivity; import { loadParticlesAttractInteraction } from tsparticles/interaction-particles-attract; (async () { await loadInteractivityPlugin(tsParticles); await loadParticlesAttractInteraction(tsParticles); })();加载函数做了什么从源码看注册链路加载函数的完整实现见 index.ts其核心逻辑非常简洁export async function loadParticlesAttractInteraction(engine: Engine): Promisevoid { engine.checkVersion(__VERSION__); await engine.pluginManager.register((e: InteractivityEngine) { ensureInteractivityPluginLoaded(e); e.pluginManager.addInteractor?.(particlesAttract, container { return Promise.resolve(new Attractor(container)); }); }); }从源码结构看这里有三点值得注意ensureInteractivityPluginLoaded(e)会显式校验 interactivity 插件是否已注册这正是 README 中“必须在tsParticles.load(...)之前调用加载函数”这一约束的代码来源插件通过e.pluginManager.addInteractor?.(particlesAttract, ...)将自身以固定名字particlesAttract注册到 interactivity 插件管理器中。这个注册入口在 plugins/interactivity/src/index.ts 中实现index.lazy.ts中也提供了对应的懒加载版本运行时interactivity 插件的InteractionManager会通过this.#pluginManager.getInteractors?.(this.#container, true)见 InteractionManager.ts拉取所有已注册的粒子交互器实例Attractor即在其中被实例化并挂到容器上参与每帧计算。选项映射Option Mappingparticles.attract 参数全解README 中给出的主选项键是particles.attract最小启用配置为{ particles: { attract: { enable: true } } }结合选项类 Options/Classes/Attract.ts 与接口 IAttract.ts该选项组共包含三个参数默认值如下表参数类型默认值作用particles.attract.enablebooleanfalse总开关。关闭时Attractor.interact()直接返回不产生任何计算particles.attract.distanceRangeValue数值或数值范围200吸引生效半径像素。每个粒子只在以自身为圆心、distance为半径的圆内寻找吸引对象particles.attract.rotate.x/rotate.y数值3000/3000X/Y 方向的吸引强度系数。数值越大单位距离产生的速度修正越小吸引效果越“温和”distance的解析入口在Attractor.interact()中首次交互时通过getRangeValue(p1.options.attract.distance)取值支持范围值随机再乘以container.retina.pixelRatio适配高分屏随后缓存到粒子属性attractDistance上见 Types.ts 中AttractParticle类型对该字段的扩展避免每帧重复解析。注意enable默认为false只安装插件而不写入enable: true时吸引效果不会生效——这是排查“为什么没有效果”时的第一检查点。原理解析Attractor 每帧如何计算吸引力核心实现在 Attractor.ts。该类继承自 interactivity 插件的ParticlesInteractorBase基类ParticlesInteractorBase.ts该基类约定了type、maxDistance、clear、init、interact、isEnabled、reset等交互器契约而Attractor中的clear()/init()/reset()均为空实现说明粒子吸引是无状态交互——它不记录任何中间状态只在interact()中直接修改粒子速度。interact()的完整流程可以拆解为四步1. 总开关与半径缓存if (!p1.options.attract?.enable) { return; } if (isNull(p1.attractDistance)) { const attractDistance getRangeValue(p1.options.attract.distance); // 记录全局最大半径供 InteractionManager 判定扫描范围 if (attractDistance this.#maxDistance) { this.#maxDistance attractDistance; } p1.attractDistance attractDistance * container.retina.pixelRatio; }#maxDistance是一个随帧内粒子遍历单调取最大值的全局上限从源码结构看它是为了给外层交互管理器提供“本交互器最远作用半径”的元信息。2. 空间网格查询邻居const query container.particles.grid.queryCircle(pos1, distance) as AttractParticle[];引擎没有做 O(n²) 的全量两两比较而是调用粒子空间网格的queryCircle(pos1, distance)只取出半径distance内的候选粒子p2并对四种无效情况直接跳过自身p1 p2、未开启吸引!p2.options.attract?.enable、已销毁p2.destroyed、正在生成中p2.spawning。3. 计算方向与强度const attractFactor 1000; // 文件级常量 const { dx, dy } getDistances(pos1, pos2); const ax dx / (rotate.x * attractFactor); const ay dy / (rotate.y * attractFactor);吸引力向量就是两点差值(dx, dy)归一化到“强度分母”上rotate.x * 1000是分母所以rotate.x 3000时相当于把位移差缩小为dx / 3000000量级的速度增量——每帧的修正量很小多帧累积后形成平滑的趋近动画而不是瞬移吸附。4. 按尺寸加权、成对反向施速const p1Factor p2.size.value / p1.size.value, p2Factor identity / p1Factor; p1.velocity.x - ax * p1Factor; p1.velocity.y - ay * p1Factor; p2.velocity.x ax * p2Factor; p2.velocity.y ay * p2Factor;这一步体现了“物理感”以两粒子的尺寸比p2.size / p1.size作为权重p1沿指向p2的方向减速/加速p2以互补权重沿相反方向实际是指向p1的方向修正速度。可以推断这模拟的是“质量大的粒子被拉动得更慢”的动量思想——尺寸大的粒子对吸引效果的响应更迟钝小粒子更快被吸向大粒子。配合maxDistance的公开 getterInteractionManager在调度时也获得了该交互器的作用半径信息保证网格查询和帧循环的范围计算一致。常见坑Common PitfallsREADME 明确列出了三个易错点结合源码可以进一步解释其成因在loadInteractivityPlugin(...)之前调用tsParticles.load(...)Attractor的基类、交互器注册表都由 interactivity 插件建立加载顺序颠倒会导致particlesAttract交互器从未被注册particles.attract配置静默失效不报错、无效果。加载函数中的ensureInteractivityPluginLoaded(e)也会在插件顺序错误时直接拦截启用高级选项前先确认依赖包除 interactivity 插件外本包不额外依赖其他插件但如果你的容器同时启用了 motion、move 等插件注意它们与速度修正类交互叠加后的表现建议核对各包的 peer 依赖声明见本包 package.json每次只改动一个选项组distance、rotate.x、rotate.y三个参数会同时改变最终速度增量一次只调一项可以快速定位是“作用范围问题”还是“强度问题”。小结tsparticles/interaction-particles-attract是一个典型的 tsParticles 粒子交互插件入口函数loadParticlesAttractInteraction负责把Attractor以particlesAttract之名注册进 interactivity 插件管理器Attractor在每帧对每个开启吸引的粒子执行“网格查邻 → 位移差除以rotate × 1000→ 按尺寸比成对反向修正速度”的三步计算。使用时只需记住 README 的检查清单先装引擎与 interactivity 插件再调用 loader最后在配置中打开particles.attract.enable并按需调整distance默认 200与rotate.x/y默认 3000两个强度参数即可得到平滑的粒子互吸效果。【免费下载链接】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),仅供参考