UNPKG

318 kBJavaScriptView Raw
1/*!
2 * Author : Matteo Bruni
3 * MIT license: https://opensource.org/licenses/MIT
4 * Demo / Generator : https://particles.js.org/
5 * GitHub : https://www.github.com/matteobruni/tsparticles
6 * How to use? : Check the GitHub README
7 * v2.12.0
8 */
9(function webpackUniversalModuleDefinition(root, factory) {
10 if(typeof exports === 'object' && typeof module === 'object')
11 module.exports = factory();
12 else if(typeof define === 'function' && define.amd)
13 define([], factory);
14 else {
15 var a = factory();
16 for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
17 }
18})(this, () => {
19return /******/ (() => { // webpackBootstrap
20/******/ "use strict";
21/******/ // The require scope
22/******/ var __webpack_require__ = {};
23/******/
24/************************************************************************/
25/******/ /* webpack/runtime/define property getters */
26/******/ (() => {
27/******/ // define getter functions for harmony exports
28/******/ __webpack_require__.d = (exports, definition) => {
29/******/ for(var key in definition) {
30/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
31/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
32/******/ }
33/******/ }
34/******/ };
35/******/ })();
36/******/
37/******/ /* webpack/runtime/hasOwnProperty shorthand */
38/******/ (() => {
39/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
40/******/ })();
41/******/
42/******/ /* webpack/runtime/make namespace object */
43/******/ (() => {
44/******/ // define __esModule on exports
45/******/ __webpack_require__.r = (exports) => {
46/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
47/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
48/******/ }
49/******/ Object.defineProperty(exports, '__esModule', { value: true });
50/******/ };
51/******/ })();
52/******/
53/************************************************************************/
54var __webpack_exports__ = {};
55// ESM COMPAT FLAG
56__webpack_require__.r(__webpack_exports__);
57
58// EXPORTS
59__webpack_require__.d(__webpack_exports__, {
60 AnimatableColor: () => (/* reexport */ AnimatableColor),
61 AnimationOptions: () => (/* reexport */ AnimationOptions),
62 AnimationValueWithRandom: () => (/* reexport */ AnimationValueWithRandom),
63 Background: () => (/* reexport */ Background),
64 BackgroundMask: () => (/* reexport */ BackgroundMask),
65 BackgroundMaskCover: () => (/* reexport */ BackgroundMaskCover),
66 Circle: () => (/* reexport */ Circle),
67 ClickEvent: () => (/* reexport */ ClickEvent),
68 Collisions: () => (/* reexport */ Collisions),
69 CollisionsAbsorb: () => (/* reexport */ CollisionsAbsorb),
70 CollisionsOverlap: () => (/* reexport */ CollisionsOverlap),
71 ColorAnimation: () => (/* reexport */ ColorAnimation),
72 DivEvent: () => (/* reexport */ DivEvent),
73 Events: () => (/* reexport */ Events),
74 ExternalInteractorBase: () => (/* reexport */ ExternalInteractorBase),
75 FullScreen: () => (/* reexport */ FullScreen),
76 HoverEvent: () => (/* reexport */ HoverEvent),
77 HslAnimation: () => (/* reexport */ HslAnimation),
78 HslColorManager: () => (/* reexport */ HslColorManager),
79 Interactivity: () => (/* reexport */ Interactivity),
80 ManualParticle: () => (/* reexport */ ManualParticle),
81 Modes: () => (/* reexport */ Modes),
82 Move: () => (/* reexport */ Move),
83 MoveAngle: () => (/* reexport */ MoveAngle),
84 MoveAttract: () => (/* reexport */ MoveAttract),
85 MoveCenter: () => (/* reexport */ MoveCenter),
86 MoveGravity: () => (/* reexport */ MoveGravity),
87 MovePath: () => (/* reexport */ MovePath),
88 MoveTrail: () => (/* reexport */ MoveTrail),
89 Opacity: () => (/* reexport */ Opacity),
90 OpacityAnimation: () => (/* reexport */ OpacityAnimation),
91 Options: () => (/* reexport */ Options),
92 OptionsColor: () => (/* reexport */ OptionsColor),
93 OutModes: () => (/* reexport */ OutModes),
94 Parallax: () => (/* reexport */ Parallax),
95 ParticlesBounce: () => (/* reexport */ ParticlesBounce),
96 ParticlesBounceFactor: () => (/* reexport */ ParticlesBounceFactor),
97 ParticlesDensity: () => (/* reexport */ ParticlesDensity),
98 ParticlesInteractorBase: () => (/* reexport */ ParticlesInteractorBase),
99 ParticlesNumber: () => (/* reexport */ ParticlesNumber),
100 ParticlesOptions: () => (/* reexport */ ParticlesOptions),
101 Point: () => (/* reexport */ Point),
102 Range: () => (/* reexport */ Range),
103 RangedAnimationOptions: () => (/* reexport */ RangedAnimationOptions),
104 RangedAnimationValueWithRandom: () => (/* reexport */ RangedAnimationValueWithRandom),
105 Rectangle: () => (/* reexport */ Rectangle),
106 ResizeEvent: () => (/* reexport */ ResizeEvent),
107 Responsive: () => (/* reexport */ Responsive),
108 RgbColorManager: () => (/* reexport */ RgbColorManager),
109 Shadow: () => (/* reexport */ Shadow),
110 Shape: () => (/* reexport */ Shape),
111 Size: () => (/* reexport */ Size),
112 SizeAnimation: () => (/* reexport */ SizeAnimation),
113 Spin: () => (/* reexport */ Spin),
114 Stroke: () => (/* reexport */ Stroke),
115 Theme: () => (/* reexport */ Theme),
116 ThemeDefault: () => (/* reexport */ ThemeDefault),
117 ValueWithRandom: () => (/* reexport */ ValueWithRandom),
118 Vector: () => (/* reexport */ Vector),
119 Vector3d: () => (/* reexport */ Vector3d),
120 ZIndex: () => (/* reexport */ ZIndex),
121 addColorManager: () => (/* reexport */ addColorManager),
122 addEasing: () => (/* reexport */ addEasing),
123 alterHsl: () => (/* reexport */ alterHsl),
124 areBoundsInside: () => (/* reexport */ areBoundsInside),
125 arrayRandomIndex: () => (/* reexport */ arrayRandomIndex),
126 calcExactPositionOrRandomFromSize: () => (/* reexport */ calcExactPositionOrRandomFromSize),
127 calcExactPositionOrRandomFromSizeRanged: () => (/* reexport */ calcExactPositionOrRandomFromSizeRanged),
128 calcPositionFromSize: () => (/* reexport */ calcPositionFromSize),
129 calcPositionOrRandomFromSize: () => (/* reexport */ calcPositionOrRandomFromSize),
130 calcPositionOrRandomFromSizeRanged: () => (/* reexport */ calcPositionOrRandomFromSizeRanged),
131 calculateBounds: () => (/* reexport */ calculateBounds),
132 circleBounce: () => (/* reexport */ circleBounce),
133 circleBounceDataFromParticle: () => (/* reexport */ circleBounceDataFromParticle),
134 clamp: () => (/* reexport */ clamp),
135 clear: () => (/* reexport */ clear),
136 collisionVelocity: () => (/* reexport */ collisionVelocity),
137 colorMix: () => (/* reexport */ colorMix),
138 colorToHsl: () => (/* reexport */ colorToHsl),
139 colorToRgb: () => (/* reexport */ colorToRgb),
140 deepExtend: () => (/* reexport */ deepExtend),
141 divMode: () => (/* reexport */ divMode),
142 divModeExecute: () => (/* reexport */ divModeExecute),
143 drawLine: () => (/* reexport */ drawLine),
144 drawParticle: () => (/* reexport */ drawParticle),
145 drawParticlePlugin: () => (/* reexport */ drawParticlePlugin),
146 drawPlugin: () => (/* reexport */ drawPlugin),
147 drawShape: () => (/* reexport */ drawShape),
148 drawShapeAfterEffect: () => (/* reexport */ drawShapeAfterEffect),
149 drawTriangle: () => (/* reexport */ drawTriangle),
150 errorPrefix: () => (/* reexport */ errorPrefix),
151 executeOnSingleOrMultiple: () => (/* reexport */ executeOnSingleOrMultiple),
152 findItemFromSingleOrMultiple: () => (/* reexport */ findItemFromSingleOrMultiple),
153 generatedAttribute: () => (/* reexport */ generatedAttribute),
154 getDistance: () => (/* reexport */ getDistance),
155 getDistances: () => (/* reexport */ getDistances),
156 getEasing: () => (/* reexport */ getEasing),
157 getHslAnimationFromHsl: () => (/* reexport */ getHslAnimationFromHsl),
158 getHslFromAnimation: () => (/* reexport */ getHslFromAnimation),
159 getLinkColor: () => (/* reexport */ getLinkColor),
160 getLinkRandomColor: () => (/* reexport */ getLinkRandomColor),
161 getLogger: () => (/* reexport */ getLogger),
162 getParticleBaseVelocity: () => (/* reexport */ getParticleBaseVelocity),
163 getParticleDirectionAngle: () => (/* reexport */ getParticleDirectionAngle),
164 getPosition: () => (/* reexport */ getPosition),
165 getRandom: () => (/* reexport */ getRandom),
166 getRandomRgbColor: () => (/* reexport */ getRandomRgbColor),
167 getRangeMax: () => (/* reexport */ getRangeMax),
168 getRangeMin: () => (/* reexport */ getRangeMin),
169 getRangeValue: () => (/* reexport */ getRangeValue),
170 getSize: () => (/* reexport */ getSize),
171 getStyleFromHsl: () => (/* reexport */ getStyleFromHsl),
172 getStyleFromRgb: () => (/* reexport */ getStyleFromRgb),
173 getValue: () => (/* reexport */ getValue),
174 hasMatchMedia: () => (/* reexport */ hasMatchMedia),
175 hslToRgb: () => (/* reexport */ hslToRgb),
176 hslaToRgba: () => (/* reexport */ hslaToRgba),
177 initParticleNumericAnimationValue: () => (/* reexport */ initParticleNumericAnimationValue),
178 isArray: () => (/* reexport */ isArray),
179 isBoolean: () => (/* reexport */ isBoolean),
180 isDivModeEnabled: () => (/* reexport */ isDivModeEnabled),
181 isFunction: () => (/* reexport */ isFunction),
182 isInArray: () => (/* reexport */ isInArray),
183 isNumber: () => (/* reexport */ isNumber),
184 isObject: () => (/* reexport */ isObject),
185 isPointInside: () => (/* reexport */ isPointInside),
186 isSsr: () => (/* reexport */ isSsr),
187 isString: () => (/* reexport */ isString),
188 itemFromArray: () => (/* reexport */ itemFromArray),
189 itemFromSingleOrMultiple: () => (/* reexport */ itemFromSingleOrMultiple),
190 loadFont: () => (/* reexport */ loadFont),
191 loadOptions: () => (/* reexport */ loadOptions),
192 loadParticlesOptions: () => (/* reexport */ loadParticlesOptions),
193 loadSlim: () => (/* reexport */ loadSlim),
194 mix: () => (/* reexport */ mix),
195 mouseDownEvent: () => (/* reexport */ mouseDownEvent),
196 mouseLeaveEvent: () => (/* reexport */ mouseLeaveEvent),
197 mouseMoveEvent: () => (/* reexport */ mouseMoveEvent),
198 mouseOutEvent: () => (/* reexport */ mouseOutEvent),
199 mouseUpEvent: () => (/* reexport */ mouseUpEvent),
200 paintBase: () => (/* reexport */ paintBase),
201 paintImage: () => (/* reexport */ paintImage),
202 parseAlpha: () => (/* reexport */ parseAlpha),
203 randomInRange: () => (/* reexport */ randomInRange),
204 rangeColorToHsl: () => (/* reexport */ rangeColorToHsl),
205 rangeColorToRgb: () => (/* reexport */ rangeColorToRgb),
206 rectBounce: () => (/* reexport */ rectBounce),
207 resizeEvent: () => (/* reexport */ resizeEvent),
208 rgbToHsl: () => (/* reexport */ rgbToHsl),
209 safeMatchMedia: () => (/* reexport */ safeMatchMedia),
210 safeMutationObserver: () => (/* reexport */ safeMutationObserver),
211 setLogger: () => (/* reexport */ setLogger),
212 setRandom: () => (/* reexport */ setRandom),
213 setRangeValue: () => (/* reexport */ setRangeValue),
214 singleDivModeExecute: () => (/* reexport */ singleDivModeExecute),
215 stringToAlpha: () => (/* reexport */ stringToAlpha),
216 stringToRgb: () => (/* reexport */ stringToRgb),
217 touchCancelEvent: () => (/* reexport */ touchCancelEvent),
218 touchEndEvent: () => (/* reexport */ touchEndEvent),
219 touchMoveEvent: () => (/* reexport */ touchMoveEvent),
220 touchStartEvent: () => (/* reexport */ touchStartEvent),
221 tsParticles: () => (/* reexport */ tsParticles),
222 visibilityChangeEvent: () => (/* reexport */ visibilityChangeEvent)
223});
224
225;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Constants.js
226const generatedAttribute = "generated";
227const mouseDownEvent = "pointerdown";
228const mouseUpEvent = "pointerup";
229const mouseLeaveEvent = "pointerleave";
230const mouseOutEvent = "pointerout";
231const mouseMoveEvent = "pointermove";
232const touchStartEvent = "touchstart";
233const touchEndEvent = "touchend";
234const touchMoveEvent = "touchmove";
235const touchCancelEvent = "touchcancel";
236const resizeEvent = "resize";
237const visibilityChangeEvent = "visibilitychange";
238const errorPrefix = "tsParticles - Error";
239;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Vector3d.js
240
241
242class Vector3d {
243 constructor(xOrCoords, y, z) {
244 this._updateFromAngle = (angle, length) => {
245 this.x = Math.cos(angle) * length;
246 this.y = Math.sin(angle) * length;
247 };
248 if (!isNumber(xOrCoords) && xOrCoords) {
249 this.x = xOrCoords.x;
250 this.y = xOrCoords.y;
251 const coords3d = xOrCoords;
252 this.z = coords3d.z ? coords3d.z : 0;
253 } else if (xOrCoords !== undefined && y !== undefined) {
254 this.x = xOrCoords;
255 this.y = y;
256 this.z = z ?? 0;
257 } else {
258 throw new Error(`${errorPrefix} Vector3d not initialized correctly`);
259 }
260 }
261 static get origin() {
262 return Vector3d.create(0, 0, 0);
263 }
264 get angle() {
265 return Math.atan2(this.y, this.x);
266 }
267 set angle(angle) {
268 this._updateFromAngle(angle, this.length);
269 }
270 get length() {
271 return Math.sqrt(this.getLengthSq());
272 }
273 set length(length) {
274 this._updateFromAngle(this.angle, length);
275 }
276 static clone(source) {
277 return Vector3d.create(source.x, source.y, source.z);
278 }
279 static create(x, y, z) {
280 return new Vector3d(x, y, z);
281 }
282 add(v) {
283 return Vector3d.create(this.x + v.x, this.y + v.y, this.z + v.z);
284 }
285 addTo(v) {
286 this.x += v.x;
287 this.y += v.y;
288 this.z += v.z;
289 }
290 copy() {
291 return Vector3d.clone(this);
292 }
293 distanceTo(v) {
294 return this.sub(v).length;
295 }
296 distanceToSq(v) {
297 return this.sub(v).getLengthSq();
298 }
299 div(n) {
300 return Vector3d.create(this.x / n, this.y / n, this.z / n);
301 }
302 divTo(n) {
303 this.x /= n;
304 this.y /= n;
305 this.z /= n;
306 }
307 getLengthSq() {
308 return this.x ** 2 + this.y ** 2;
309 }
310 mult(n) {
311 return Vector3d.create(this.x * n, this.y * n, this.z * n);
312 }
313 multTo(n) {
314 this.x *= n;
315 this.y *= n;
316 this.z *= n;
317 }
318 normalize() {
319 const length = this.length;
320 if (length != 0) {
321 this.multTo(1.0 / length);
322 }
323 }
324 rotate(angle) {
325 return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle), 0);
326 }
327 setTo(c) {
328 this.x = c.x;
329 this.y = c.y;
330 const v3d = c;
331 this.z = v3d.z ? v3d.z : 0;
332 }
333 sub(v) {
334 return Vector3d.create(this.x - v.x, this.y - v.y, this.z - v.z);
335 }
336 subFrom(v) {
337 this.x -= v.x;
338 this.y -= v.y;
339 this.z -= v.z;
340 }
341}
342;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Vector.js
343
344class Vector extends Vector3d {
345 constructor(xOrCoords, y) {
346 super(xOrCoords, y, 0);
347 }
348 static get origin() {
349 return Vector.create(0, 0);
350 }
351 static clone(source) {
352 return Vector.create(source.x, source.y);
353 }
354 static create(x, y) {
355 return new Vector(x, y);
356 }
357}
358;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/NumberUtils.js
359
360
361let _random = Math.random;
362const easings = new Map();
363function addEasing(name, easing) {
364 if (easings.get(name)) {
365 return;
366 }
367 easings.set(name, easing);
368}
369function getEasing(name) {
370 return easings.get(name) || (value => value);
371}
372function setRandom(rnd = Math.random) {
373 _random = rnd;
374}
375function getRandom() {
376 return clamp(_random(), 0, 1 - 1e-16);
377}
378function clamp(num, min, max) {
379 return Math.min(Math.max(num, min), max);
380}
381function mix(comp1, comp2, weight1, weight2) {
382 return Math.floor((comp1 * weight1 + comp2 * weight2) / (weight1 + weight2));
383}
384function randomInRange(r) {
385 const max = getRangeMax(r);
386 let min = getRangeMin(r);
387 if (max === min) {
388 min = 0;
389 }
390 return getRandom() * (max - min) + min;
391}
392function getRangeValue(value) {
393 return isNumber(value) ? value : randomInRange(value);
394}
395function getRangeMin(value) {
396 return isNumber(value) ? value : value.min;
397}
398function getRangeMax(value) {
399 return isNumber(value) ? value : value.max;
400}
401function setRangeValue(source, value) {
402 if (source === value || value === undefined && isNumber(source)) {
403 return source;
404 }
405 const min = getRangeMin(source),
406 max = getRangeMax(source);
407 return value !== undefined ? {
408 min: Math.min(min, value),
409 max: Math.max(max, value)
410 } : setRangeValue(min, max);
411}
412function getValue(options) {
413 const random = options.random,
414 {
415 enable,
416 minimumValue
417 } = isBoolean(random) ? {
418 enable: random,
419 minimumValue: 0
420 } : random;
421 return enable ? getRangeValue(setRangeValue(options.value, minimumValue)) : getRangeValue(options.value);
422}
423function getDistances(pointA, pointB) {
424 const dx = pointA.x - pointB.x,
425 dy = pointA.y - pointB.y;
426 return {
427 dx: dx,
428 dy: dy,
429 distance: Math.sqrt(dx ** 2 + dy ** 2)
430 };
431}
432function getDistance(pointA, pointB) {
433 return getDistances(pointA, pointB).distance;
434}
435function getParticleDirectionAngle(direction, position, center) {
436 if (isNumber(direction)) {
437 return direction * Math.PI / 180;
438 }
439 switch (direction) {
440 case "top":
441 return -Math.PI / 2;
442 case "top-right":
443 return -Math.PI / 4;
444 case "right":
445 return 0;
446 case "bottom-right":
447 return Math.PI / 4;
448 case "bottom":
449 return Math.PI / 2;
450 case "bottom-left":
451 return 3 * Math.PI / 4;
452 case "left":
453 return Math.PI;
454 case "top-left":
455 return -3 * Math.PI / 4;
456 case "inside":
457 return Math.atan2(center.y - position.y, center.x - position.x);
458 case "outside":
459 return Math.atan2(position.y - center.y, position.x - center.x);
460 default:
461 return getRandom() * Math.PI * 2;
462 }
463}
464function getParticleBaseVelocity(direction) {
465 const baseVelocity = Vector.origin;
466 baseVelocity.length = 1;
467 baseVelocity.angle = direction;
468 return baseVelocity;
469}
470function collisionVelocity(v1, v2, m1, m2) {
471 return Vector.create(v1.x * (m1 - m2) / (m1 + m2) + v2.x * 2 * m2 / (m1 + m2), v1.y);
472}
473function calcPositionFromSize(data) {
474 return data.position && data.position.x !== undefined && data.position.y !== undefined ? {
475 x: data.position.x * data.size.width / 100,
476 y: data.position.y * data.size.height / 100
477 } : undefined;
478}
479function calcPositionOrRandomFromSize(data) {
480 return {
481 x: (data.position?.x ?? getRandom() * 100) * data.size.width / 100,
482 y: (data.position?.y ?? getRandom() * 100) * data.size.height / 100
483 };
484}
485function calcPositionOrRandomFromSizeRanged(data) {
486 const position = {
487 x: data.position?.x !== undefined ? getRangeValue(data.position.x) : undefined,
488 y: data.position?.y !== undefined ? getRangeValue(data.position.y) : undefined
489 };
490 return calcPositionOrRandomFromSize({
491 size: data.size,
492 position
493 });
494}
495function calcExactPositionOrRandomFromSize(data) {
496 return {
497 x: data.position?.x ?? getRandom() * data.size.width,
498 y: data.position?.y ?? getRandom() * data.size.height
499 };
500}
501function calcExactPositionOrRandomFromSizeRanged(data) {
502 const position = {
503 x: data.position?.x !== undefined ? getRangeValue(data.position.x) : undefined,
504 y: data.position?.y !== undefined ? getRangeValue(data.position.y) : undefined
505 };
506 return calcExactPositionOrRandomFromSize({
507 size: data.size,
508 position
509 });
510}
511function parseAlpha(input) {
512 return input ? input.endsWith("%") ? parseFloat(input) / 100 : parseFloat(input) : 1;
513}
514;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/Utils.js
515
516
517const _logger = {
518 debug: console.debug,
519 error: console.error,
520 info: console.info,
521 log: console.log,
522 verbose: console.log,
523 warning: console.warn
524};
525function setLogger(logger) {
526 _logger.debug = logger.debug || _logger.debug;
527 _logger.error = logger.error || _logger.error;
528 _logger.info = logger.info || _logger.info;
529 _logger.log = logger.log || _logger.log;
530 _logger.verbose = logger.verbose || _logger.verbose;
531 _logger.warning = logger.warning || _logger.warning;
532}
533function getLogger() {
534 return _logger;
535}
536function rectSideBounce(data) {
537 const res = {
538 bounced: false
539 },
540 {
541 pSide,
542 pOtherSide,
543 rectSide,
544 rectOtherSide,
545 velocity,
546 factor
547 } = data;
548 if (pOtherSide.min < rectOtherSide.min || pOtherSide.min > rectOtherSide.max || pOtherSide.max < rectOtherSide.min || pOtherSide.max > rectOtherSide.max) {
549 return res;
550 }
551 if (pSide.max >= rectSide.min && pSide.max <= (rectSide.max + rectSide.min) / 2 && velocity > 0 || pSide.min <= rectSide.max && pSide.min > (rectSide.max + rectSide.min) / 2 && velocity < 0) {
552 res.velocity = velocity * -factor;
553 res.bounced = true;
554 }
555 return res;
556}
557function checkSelector(element, selectors) {
558 const res = executeOnSingleOrMultiple(selectors, selector => {
559 return element.matches(selector);
560 });
561 return isArray(res) ? res.some(t => t) : res;
562}
563function isSsr() {
564 return typeof window === "undefined" || !window || typeof window.document === "undefined" || !window.document;
565}
566function hasMatchMedia() {
567 return !isSsr() && typeof matchMedia !== "undefined";
568}
569function safeMatchMedia(query) {
570 if (!hasMatchMedia()) {
571 return;
572 }
573 return matchMedia(query);
574}
575function safeMutationObserver(callback) {
576 if (isSsr() || typeof MutationObserver === "undefined") {
577 return;
578 }
579 return new MutationObserver(callback);
580}
581function isInArray(value, array) {
582 return value === array || isArray(array) && array.indexOf(value) > -1;
583}
584async function loadFont(font, weight) {
585 try {
586 await document.fonts.load(`${weight ?? "400"} 36px '${font ?? "Verdana"}'`);
587 } catch {}
588}
589function arrayRandomIndex(array) {
590 return Math.floor(getRandom() * array.length);
591}
592function itemFromArray(array, index, useIndex = true) {
593 return array[index !== undefined && useIndex ? index % array.length : arrayRandomIndex(array)];
594}
595function isPointInside(point, size, offset, radius, direction) {
596 return areBoundsInside(calculateBounds(point, radius ?? 0), size, offset, direction);
597}
598function areBoundsInside(bounds, size, offset, direction) {
599 let inside = true;
600 if (!direction || direction === "bottom") {
601 inside = bounds.top < size.height + offset.x;
602 }
603 if (inside && (!direction || direction === "left")) {
604 inside = bounds.right > offset.x;
605 }
606 if (inside && (!direction || direction === "right")) {
607 inside = bounds.left < size.width + offset.y;
608 }
609 if (inside && (!direction || direction === "top")) {
610 inside = bounds.bottom > offset.y;
611 }
612 return inside;
613}
614function calculateBounds(point, radius) {
615 return {
616 bottom: point.y + radius,
617 left: point.x - radius,
618 right: point.x + radius,
619 top: point.y - radius
620 };
621}
622function deepExtend(destination, ...sources) {
623 for (const source of sources) {
624 if (source === undefined || source === null) {
625 continue;
626 }
627 if (!isObject(source)) {
628 destination = source;
629 continue;
630 }
631 const sourceIsArray = Array.isArray(source);
632 if (sourceIsArray && (isObject(destination) || !destination || !Array.isArray(destination))) {
633 destination = [];
634 } else if (!sourceIsArray && (isObject(destination) || !destination || Array.isArray(destination))) {
635 destination = {};
636 }
637 for (const key in source) {
638 if (key === "__proto__") {
639 continue;
640 }
641 const sourceDict = source,
642 value = sourceDict[key],
643 destDict = destination;
644 destDict[key] = isObject(value) && Array.isArray(value) ? value.map(v => deepExtend(destDict[key], v)) : deepExtend(destDict[key], value);
645 }
646 }
647 return destination;
648}
649function isDivModeEnabled(mode, divs) {
650 return !!findItemFromSingleOrMultiple(divs, t => t.enable && isInArray(mode, t.mode));
651}
652function divModeExecute(mode, divs, callback) {
653 executeOnSingleOrMultiple(divs, div => {
654 const divMode = div.mode,
655 divEnabled = div.enable;
656 if (divEnabled && isInArray(mode, divMode)) {
657 singleDivModeExecute(div, callback);
658 }
659 });
660}
661function singleDivModeExecute(div, callback) {
662 const selectors = div.selectors;
663 executeOnSingleOrMultiple(selectors, selector => {
664 callback(selector, div);
665 });
666}
667function divMode(divs, element) {
668 if (!element || !divs) {
669 return;
670 }
671 return findItemFromSingleOrMultiple(divs, div => {
672 return checkSelector(element, div.selectors);
673 });
674}
675function circleBounceDataFromParticle(p) {
676 return {
677 position: p.getPosition(),
678 radius: p.getRadius(),
679 mass: p.getMass(),
680 velocity: p.velocity,
681 factor: Vector.create(getValue(p.options.bounce.horizontal), getValue(p.options.bounce.vertical))
682 };
683}
684function circleBounce(p1, p2) {
685 const {
686 x: xVelocityDiff,
687 y: yVelocityDiff
688 } = p1.velocity.sub(p2.velocity),
689 [pos1, pos2] = [p1.position, p2.position],
690 {
691 dx: xDist,
692 dy: yDist
693 } = getDistances(pos2, pos1);
694 if (xVelocityDiff * xDist + yVelocityDiff * yDist < 0) {
695 return;
696 }
697 const angle = -Math.atan2(yDist, xDist),
698 m1 = p1.mass,
699 m2 = p2.mass,
700 u1 = p1.velocity.rotate(angle),
701 u2 = p2.velocity.rotate(angle),
702 v1 = collisionVelocity(u1, u2, m1, m2),
703 v2 = collisionVelocity(u2, u1, m1, m2),
704 vFinal1 = v1.rotate(-angle),
705 vFinal2 = v2.rotate(-angle);
706 p1.velocity.x = vFinal1.x * p1.factor.x;
707 p1.velocity.y = vFinal1.y * p1.factor.y;
708 p2.velocity.x = vFinal2.x * p2.factor.x;
709 p2.velocity.y = vFinal2.y * p2.factor.y;
710}
711function rectBounce(particle, divBounds) {
712 const pPos = particle.getPosition(),
713 size = particle.getRadius(),
714 bounds = calculateBounds(pPos, size),
715 resH = rectSideBounce({
716 pSide: {
717 min: bounds.left,
718 max: bounds.right
719 },
720 pOtherSide: {
721 min: bounds.top,
722 max: bounds.bottom
723 },
724 rectSide: {
725 min: divBounds.left,
726 max: divBounds.right
727 },
728 rectOtherSide: {
729 min: divBounds.top,
730 max: divBounds.bottom
731 },
732 velocity: particle.velocity.x,
733 factor: getValue(particle.options.bounce.horizontal)
734 });
735 if (resH.bounced) {
736 if (resH.velocity !== undefined) {
737 particle.velocity.x = resH.velocity;
738 }
739 if (resH.position !== undefined) {
740 particle.position.x = resH.position;
741 }
742 }
743 const resV = rectSideBounce({
744 pSide: {
745 min: bounds.top,
746 max: bounds.bottom
747 },
748 pOtherSide: {
749 min: bounds.left,
750 max: bounds.right
751 },
752 rectSide: {
753 min: divBounds.top,
754 max: divBounds.bottom
755 },
756 rectOtherSide: {
757 min: divBounds.left,
758 max: divBounds.right
759 },
760 velocity: particle.velocity.y,
761 factor: getValue(particle.options.bounce.vertical)
762 });
763 if (resV.bounced) {
764 if (resV.velocity !== undefined) {
765 particle.velocity.y = resV.velocity;
766 }
767 if (resV.position !== undefined) {
768 particle.position.y = resV.position;
769 }
770 }
771}
772function executeOnSingleOrMultiple(obj, callback) {
773 return isArray(obj) ? obj.map((item, index) => callback(item, index)) : callback(obj, 0);
774}
775function itemFromSingleOrMultiple(obj, index, useIndex) {
776 return isArray(obj) ? itemFromArray(obj, index, useIndex) : obj;
777}
778function findItemFromSingleOrMultiple(obj, callback) {
779 return isArray(obj) ? obj.find((t, index) => callback(t, index)) : callback(obj, 0) ? obj : undefined;
780}
781function initParticleNumericAnimationValue(options, pxRatio) {
782 const valueRange = options.value,
783 animationOptions = options.animation,
784 res = {
785 delayTime: getRangeValue(animationOptions.delay) * 1000,
786 enable: animationOptions.enable,
787 value: getRangeValue(options.value) * pxRatio,
788 max: getRangeMax(valueRange) * pxRatio,
789 min: getRangeMin(valueRange) * pxRatio,
790 loops: 0,
791 maxLoops: getRangeValue(animationOptions.count),
792 time: 0
793 };
794 if (animationOptions.enable) {
795 res.decay = 1 - getRangeValue(animationOptions.decay);
796 switch (animationOptions.mode) {
797 case "increase":
798 res.status = "increasing";
799 break;
800 case "decrease":
801 res.status = "decreasing";
802 break;
803 case "random":
804 res.status = getRandom() >= 0.5 ? "increasing" : "decreasing";
805 break;
806 }
807 const autoStatus = animationOptions.mode === "auto";
808 switch (animationOptions.startValue) {
809 case "min":
810 res.value = res.min;
811 if (autoStatus) {
812 res.status = "increasing";
813 }
814 break;
815 case "max":
816 res.value = res.max;
817 if (autoStatus) {
818 res.status = "decreasing";
819 }
820 break;
821 case "random":
822 default:
823 res.value = randomInRange(res);
824 if (autoStatus) {
825 res.status = getRandom() >= 0.5 ? "increasing" : "decreasing";
826 }
827 break;
828 }
829 }
830 res.initialValue = res.value;
831 return res;
832}
833function getPositionOrSize(positionOrSize, canvasSize) {
834 const isPercent = positionOrSize.mode === "percent";
835 if (!isPercent) {
836 const {
837 mode: _,
838 ...rest
839 } = positionOrSize;
840 return rest;
841 }
842 const isPosition = ("x" in positionOrSize);
843 if (isPosition) {
844 return {
845 x: positionOrSize.x / 100 * canvasSize.width,
846 y: positionOrSize.y / 100 * canvasSize.height
847 };
848 } else {
849 return {
850 width: positionOrSize.width / 100 * canvasSize.width,
851 height: positionOrSize.height / 100 * canvasSize.height
852 };
853 }
854}
855function getPosition(position, canvasSize) {
856 return getPositionOrSize(position, canvasSize);
857}
858function getSize(size, canvasSize) {
859 return getPositionOrSize(size, canvasSize);
860}
861function isBoolean(arg) {
862 return typeof arg === "boolean";
863}
864function isString(arg) {
865 return typeof arg === "string";
866}
867function isNumber(arg) {
868 return typeof arg === "number";
869}
870function isFunction(arg) {
871 return typeof arg === "function";
872}
873function isObject(arg) {
874 return typeof arg === "object" && arg !== null;
875}
876function isArray(arg) {
877 return Array.isArray(arg);
878}
879;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/ColorUtils.js
880
881
882const randomColorValue = "random",
883 midColorValue = "mid",
884 colorManagers = new Map();
885function addColorManager(manager) {
886 colorManagers.set(manager.key, manager);
887}
888function hue2rgb(p, q, t) {
889 if (t < 0) {
890 t += 1;
891 }
892 if (t > 1) {
893 t -= 1;
894 }
895 if (t < 1 / 6) {
896 return p + (q - p) * 6 * t;
897 }
898 if (t < 1 / 2) {
899 return q;
900 }
901 if (t < 2 / 3) {
902 return p + (q - p) * (2 / 3 - t) * 6;
903 }
904 return p;
905}
906function stringToRgba(input) {
907 for (const [, manager] of colorManagers) {
908 if (input.startsWith(manager.stringPrefix)) {
909 return manager.parseString(input);
910 }
911 }
912 const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i,
913 hexFixed = input.replace(shorthandRegex, (_, r, g, b, a) => {
914 return r + r + g + g + b + b + (a !== undefined ? a + a : "");
915 }),
916 regex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i,
917 result = regex.exec(hexFixed);
918 return result ? {
919 a: result[4] !== undefined ? parseInt(result[4], 16) / 0xff : 1,
920 b: parseInt(result[3], 16),
921 g: parseInt(result[2], 16),
922 r: parseInt(result[1], 16)
923 } : undefined;
924}
925function rangeColorToRgb(input, index, useIndex = true) {
926 if (!input) {
927 return;
928 }
929 const color = isString(input) ? {
930 value: input
931 } : input;
932 if (isString(color.value)) {
933 return colorToRgb(color.value, index, useIndex);
934 }
935 if (isArray(color.value)) {
936 return rangeColorToRgb({
937 value: itemFromArray(color.value, index, useIndex)
938 });
939 }
940 for (const [, manager] of colorManagers) {
941 const res = manager.handleRangeColor(color);
942 if (res) {
943 return res;
944 }
945 }
946}
947function colorToRgb(input, index, useIndex = true) {
948 if (!input) {
949 return;
950 }
951 const color = isString(input) ? {
952 value: input
953 } : input;
954 if (isString(color.value)) {
955 return color.value === randomColorValue ? getRandomRgbColor() : stringToRgb(color.value);
956 }
957 if (isArray(color.value)) {
958 return colorToRgb({
959 value: itemFromArray(color.value, index, useIndex)
960 });
961 }
962 for (const [, manager] of colorManagers) {
963 const res = manager.handleColor(color);
964 if (res) {
965 return res;
966 }
967 }
968}
969function colorToHsl(color, index, useIndex = true) {
970 const rgb = colorToRgb(color, index, useIndex);
971 return rgb ? rgbToHsl(rgb) : undefined;
972}
973function rangeColorToHsl(color, index, useIndex = true) {
974 const rgb = rangeColorToRgb(color, index, useIndex);
975 return rgb ? rgbToHsl(rgb) : undefined;
976}
977function rgbToHsl(color) {
978 const r1 = color.r / 255,
979 g1 = color.g / 255,
980 b1 = color.b / 255,
981 max = Math.max(r1, g1, b1),
982 min = Math.min(r1, g1, b1),
983 res = {
984 h: 0,
985 l: (max + min) / 2,
986 s: 0
987 };
988 if (max !== min) {
989 res.s = res.l < 0.5 ? (max - min) / (max + min) : (max - min) / (2.0 - max - min);
990 res.h = r1 === max ? (g1 - b1) / (max - min) : res.h = g1 === max ? 2.0 + (b1 - r1) / (max - min) : 4.0 + (r1 - g1) / (max - min);
991 }
992 res.l *= 100;
993 res.s *= 100;
994 res.h *= 60;
995 if (res.h < 0) {
996 res.h += 360;
997 }
998 if (res.h >= 360) {
999 res.h -= 360;
1000 }
1001 return res;
1002}
1003function stringToAlpha(input) {
1004 return stringToRgba(input)?.a;
1005}
1006function stringToRgb(input) {
1007 return stringToRgba(input);
1008}
1009function hslToRgb(hsl) {
1010 const result = {
1011 b: 0,
1012 g: 0,
1013 r: 0
1014 },
1015 hslPercent = {
1016 h: hsl.h / 360,
1017 l: hsl.l / 100,
1018 s: hsl.s / 100
1019 };
1020 if (!hslPercent.s) {
1021 result.r = result.g = result.b = hslPercent.l;
1022 } else {
1023 const q = hslPercent.l < 0.5 ? hslPercent.l * (1 + hslPercent.s) : hslPercent.l + hslPercent.s - hslPercent.l * hslPercent.s,
1024 p = 2 * hslPercent.l - q;
1025 result.r = hue2rgb(p, q, hslPercent.h + 1 / 3);
1026 result.g = hue2rgb(p, q, hslPercent.h);
1027 result.b = hue2rgb(p, q, hslPercent.h - 1 / 3);
1028 }
1029 result.r = Math.floor(result.r * 255);
1030 result.g = Math.floor(result.g * 255);
1031 result.b = Math.floor(result.b * 255);
1032 return result;
1033}
1034function hslaToRgba(hsla) {
1035 const rgbResult = hslToRgb(hsla);
1036 return {
1037 a: hsla.a,
1038 b: rgbResult.b,
1039 g: rgbResult.g,
1040 r: rgbResult.r
1041 };
1042}
1043function getRandomRgbColor(min) {
1044 const fixedMin = min ?? 0;
1045 return {
1046 b: Math.floor(randomInRange(setRangeValue(fixedMin, 256))),
1047 g: Math.floor(randomInRange(setRangeValue(fixedMin, 256))),
1048 r: Math.floor(randomInRange(setRangeValue(fixedMin, 256)))
1049 };
1050}
1051function getStyleFromRgb(color, opacity) {
1052 return `rgba(${color.r}, ${color.g}, ${color.b}, ${opacity ?? 1})`;
1053}
1054function getStyleFromHsl(color, opacity) {
1055 return `hsla(${color.h}, ${color.s}%, ${color.l}%, ${opacity ?? 1})`;
1056}
1057function colorMix(color1, color2, size1, size2) {
1058 let rgb1 = color1,
1059 rgb2 = color2;
1060 if (rgb1.r === undefined) {
1061 rgb1 = hslToRgb(color1);
1062 }
1063 if (rgb2.r === undefined) {
1064 rgb2 = hslToRgb(color2);
1065 }
1066 return {
1067 b: mix(rgb1.b, rgb2.b, size1, size2),
1068 g: mix(rgb1.g, rgb2.g, size1, size2),
1069 r: mix(rgb1.r, rgb2.r, size1, size2)
1070 };
1071}
1072function getLinkColor(p1, p2, linkColor) {
1073 if (linkColor === randomColorValue) {
1074 return getRandomRgbColor();
1075 } else if (linkColor === midColorValue) {
1076 const sourceColor = p1.getFillColor() ?? p1.getStrokeColor(),
1077 destColor = p2?.getFillColor() ?? p2?.getStrokeColor();
1078 if (sourceColor && destColor && p2) {
1079 return colorMix(sourceColor, destColor, p1.getRadius(), p2.getRadius());
1080 } else {
1081 const hslColor = sourceColor ?? destColor;
1082 if (hslColor) {
1083 return hslToRgb(hslColor);
1084 }
1085 }
1086 } else {
1087 return linkColor;
1088 }
1089}
1090function getLinkRandomColor(optColor, blink, consent) {
1091 const color = isString(optColor) ? optColor : optColor.value;
1092 if (color === randomColorValue) {
1093 if (consent) {
1094 return rangeColorToRgb({
1095 value: color
1096 });
1097 }
1098 if (blink) {
1099 return randomColorValue;
1100 }
1101 return midColorValue;
1102 } else if (color === midColorValue) {
1103 return midColorValue;
1104 } else {
1105 return rangeColorToRgb({
1106 value: color
1107 });
1108 }
1109}
1110function getHslFromAnimation(animation) {
1111 return animation !== undefined ? {
1112 h: animation.h.value,
1113 s: animation.s.value,
1114 l: animation.l.value
1115 } : undefined;
1116}
1117function getHslAnimationFromHsl(hsl, animationOptions, reduceFactor) {
1118 const resColor = {
1119 h: {
1120 enable: false,
1121 value: hsl.h
1122 },
1123 s: {
1124 enable: false,
1125 value: hsl.s
1126 },
1127 l: {
1128 enable: false,
1129 value: hsl.l
1130 }
1131 };
1132 if (animationOptions) {
1133 setColorAnimation(resColor.h, animationOptions.h, reduceFactor);
1134 setColorAnimation(resColor.s, animationOptions.s, reduceFactor);
1135 setColorAnimation(resColor.l, animationOptions.l, reduceFactor);
1136 }
1137 return resColor;
1138}
1139function setColorAnimation(colorValue, colorAnimation, reduceFactor) {
1140 colorValue.enable = colorAnimation.enable;
1141 if (colorValue.enable) {
1142 colorValue.velocity = getRangeValue(colorAnimation.speed) / 100 * reduceFactor;
1143 colorValue.decay = 1 - getRangeValue(colorAnimation.decay);
1144 colorValue.status = "increasing";
1145 colorValue.loops = 0;
1146 colorValue.maxLoops = getRangeValue(colorAnimation.count);
1147 colorValue.time = 0;
1148 colorValue.delayTime = getRangeValue(colorAnimation.delay) * 1000;
1149 if (!colorAnimation.sync) {
1150 colorValue.velocity *= getRandom();
1151 colorValue.value *= getRandom();
1152 }
1153 colorValue.initialValue = colorValue.value;
1154 } else {
1155 colorValue.velocity = 0;
1156 }
1157}
1158;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/CanvasUtils.js
1159
1160function drawLine(context, begin, end) {
1161 context.beginPath();
1162 context.moveTo(begin.x, begin.y);
1163 context.lineTo(end.x, end.y);
1164 context.closePath();
1165}
1166function drawTriangle(context, p1, p2, p3) {
1167 context.beginPath();
1168 context.moveTo(p1.x, p1.y);
1169 context.lineTo(p2.x, p2.y);
1170 context.lineTo(p3.x, p3.y);
1171 context.closePath();
1172}
1173function paintBase(context, dimension, baseColor) {
1174 context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1175 context.fillRect(0, 0, dimension.width, dimension.height);
1176}
1177function paintImage(context, dimension, image, opacity) {
1178 if (!image) {
1179 return;
1180 }
1181 context.globalAlpha = opacity;
1182 context.drawImage(image, 0, 0, dimension.width, dimension.height);
1183 context.globalAlpha = 1;
1184}
1185function clear(context, dimension) {
1186 context.clearRect(0, 0, dimension.width, dimension.height);
1187}
1188function drawParticle(data) {
1189 const {
1190 container,
1191 context,
1192 particle,
1193 delta,
1194 colorStyles,
1195 backgroundMask,
1196 composite,
1197 radius,
1198 opacity,
1199 shadow,
1200 transform
1201 } = data;
1202 const pos = particle.getPosition(),
1203 angle = particle.rotation + (particle.pathRotation ? particle.velocity.angle : 0),
1204 rotateData = {
1205 sin: Math.sin(angle),
1206 cos: Math.cos(angle)
1207 },
1208 transformData = {
1209 a: rotateData.cos * (transform.a ?? 1),
1210 b: rotateData.sin * (transform.b ?? 1),
1211 c: -rotateData.sin * (transform.c ?? 1),
1212 d: rotateData.cos * (transform.d ?? 1)
1213 };
1214 context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1215 context.beginPath();
1216 if (backgroundMask) {
1217 context.globalCompositeOperation = composite;
1218 }
1219 const shadowColor = particle.shadowColor;
1220 if (shadow.enable && shadowColor) {
1221 context.shadowBlur = shadow.blur;
1222 context.shadowColor = getStyleFromRgb(shadowColor);
1223 context.shadowOffsetX = shadow.offset.x;
1224 context.shadowOffsetY = shadow.offset.y;
1225 }
1226 if (colorStyles.fill) {
1227 context.fillStyle = colorStyles.fill;
1228 }
1229 const strokeWidth = particle.strokeWidth ?? 0;
1230 context.lineWidth = strokeWidth;
1231 if (colorStyles.stroke) {
1232 context.strokeStyle = colorStyles.stroke;
1233 }
1234 drawShape(container, context, particle, radius, opacity, delta);
1235 if (strokeWidth > 0) {
1236 context.stroke();
1237 }
1238 if (particle.close) {
1239 context.closePath();
1240 }
1241 if (particle.fill) {
1242 context.fill();
1243 }
1244 drawShapeAfterEffect(container, context, particle, radius, opacity, delta);
1245 context.globalCompositeOperation = "source-over";
1246 context.setTransform(1, 0, 0, 1, 0, 0);
1247}
1248function drawShape(container, context, particle, radius, opacity, delta) {
1249 if (!particle.shape) {
1250 return;
1251 }
1252 const drawer = container.drawers.get(particle.shape);
1253 if (!drawer) {
1254 return;
1255 }
1256 drawer.draw(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1257}
1258function drawShapeAfterEffect(container, context, particle, radius, opacity, delta) {
1259 if (!particle.shape) {
1260 return;
1261 }
1262 const drawer = container.drawers.get(particle.shape);
1263 if (!drawer || !drawer.afterEffect) {
1264 return;
1265 }
1266 drawer.afterEffect(context, particle, radius, opacity, delta, container.retina.pixelRatio);
1267}
1268function drawPlugin(context, plugin, delta) {
1269 if (!plugin.draw) {
1270 return;
1271 }
1272 plugin.draw(context, delta);
1273}
1274function drawParticlePlugin(context, plugin, particle, delta) {
1275 if (!plugin.drawParticle) {
1276 return;
1277 }
1278 plugin.drawParticle(context, particle, delta);
1279}
1280function alterHsl(color, type, value) {
1281 return {
1282 h: color.h,
1283 s: color.s,
1284 l: color.l + (type === "darken" ? -1 : 1) * value
1285 };
1286}
1287;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Canvas.js
1288
1289
1290
1291
1292function setTransformValue(factor, newFactor, key) {
1293 const newValue = newFactor[key];
1294 if (newValue !== undefined) {
1295 factor[key] = (factor[key] ?? 1) * newValue;
1296 }
1297}
1298class Canvas {
1299 constructor(container) {
1300 this.container = container;
1301 this._applyPostDrawUpdaters = particle => {
1302 for (const updater of this._postDrawUpdaters) {
1303 updater.afterDraw && updater.afterDraw(particle);
1304 }
1305 };
1306 this._applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
1307 for (const updater of this._preDrawUpdaters) {
1308 if (updater.getColorStyles) {
1309 const {
1310 fill,
1311 stroke
1312 } = updater.getColorStyles(particle, ctx, radius, zOpacity);
1313 if (fill) {
1314 colorStyles.fill = fill;
1315 }
1316 if (stroke) {
1317 colorStyles.stroke = stroke;
1318 }
1319 }
1320 if (updater.getTransformValues) {
1321 const updaterTransform = updater.getTransformValues(particle);
1322 for (const key in updaterTransform) {
1323 setTransformValue(transform, updaterTransform, key);
1324 }
1325 }
1326 updater.beforeDraw && updater.beforeDraw(particle);
1327 }
1328 };
1329 this._applyResizePlugins = () => {
1330 for (const plugin of this._resizePlugins) {
1331 plugin.resize && plugin.resize();
1332 }
1333 };
1334 this._getPluginParticleColors = particle => {
1335 let fColor, sColor;
1336 for (const plugin of this._colorPlugins) {
1337 if (!fColor && plugin.particleFillColor) {
1338 fColor = rangeColorToHsl(plugin.particleFillColor(particle));
1339 }
1340 if (!sColor && plugin.particleStrokeColor) {
1341 sColor = rangeColorToHsl(plugin.particleStrokeColor(particle));
1342 }
1343 if (fColor && sColor) {
1344 break;
1345 }
1346 }
1347 return [fColor, sColor];
1348 };
1349 this._initCover = () => {
1350 const options = this.container.actualOptions,
1351 cover = options.backgroundMask.cover,
1352 color = cover.color,
1353 coverRgb = rangeColorToRgb(color);
1354 if (coverRgb) {
1355 const coverColor = {
1356 ...coverRgb,
1357 a: cover.opacity
1358 };
1359 this._coverColorStyle = getStyleFromRgb(coverColor, coverColor.a);
1360 }
1361 };
1362 this._initStyle = () => {
1363 const element = this.element,
1364 options = this.container.actualOptions;
1365 if (!element) {
1366 return;
1367 }
1368 if (this._fullScreen) {
1369 this._originalStyle = deepExtend({}, element.style);
1370 this._setFullScreenStyle();
1371 } else {
1372 this._resetOriginalStyle();
1373 }
1374 for (const key in options.style) {
1375 if (!key || !options.style) {
1376 continue;
1377 }
1378 const value = options.style[key];
1379 if (!value) {
1380 continue;
1381 }
1382 element.style.setProperty(key, value, "important");
1383 }
1384 };
1385 this._initTrail = async () => {
1386 const options = this.container.actualOptions,
1387 trail = options.particles.move.trail,
1388 trailFill = trail.fill;
1389 if (!trail.enable) {
1390 return;
1391 }
1392 if (trailFill.color) {
1393 const fillColor = rangeColorToRgb(trailFill.color);
1394 if (!fillColor) {
1395 return;
1396 }
1397 const trail = options.particles.move.trail;
1398 this._trailFill = {
1399 color: {
1400 ...fillColor
1401 },
1402 opacity: 1 / trail.length
1403 };
1404 } else {
1405 await new Promise((resolve, reject) => {
1406 if (!trailFill.image) {
1407 return;
1408 }
1409 const img = document.createElement("img");
1410 img.addEventListener("load", () => {
1411 this._trailFill = {
1412 image: img,
1413 opacity: 1 / trail.length
1414 };
1415 resolve();
1416 });
1417 img.addEventListener("error", evt => {
1418 reject(evt.error);
1419 });
1420 img.src = trailFill.image;
1421 });
1422 }
1423 };
1424 this._paintBase = baseColor => {
1425 this.draw(ctx => paintBase(ctx, this.size, baseColor));
1426 };
1427 this._paintImage = (image, opacity) => {
1428 this.draw(ctx => paintImage(ctx, this.size, image, opacity));
1429 };
1430 this._repairStyle = () => {
1431 const element = this.element;
1432 if (!element) {
1433 return;
1434 }
1435 this._safeMutationObserver(observer => observer.disconnect());
1436 this._initStyle();
1437 this.initBackground();
1438 this._safeMutationObserver(observer => observer.observe(element, {
1439 attributes: true
1440 }));
1441 };
1442 this._resetOriginalStyle = () => {
1443 const element = this.element,
1444 originalStyle = this._originalStyle;
1445 if (!(element && originalStyle)) {
1446 return;
1447 }
1448 const style = element.style;
1449 style.position = originalStyle.position;
1450 style.zIndex = originalStyle.zIndex;
1451 style.top = originalStyle.top;
1452 style.left = originalStyle.left;
1453 style.width = originalStyle.width;
1454 style.height = originalStyle.height;
1455 };
1456 this._safeMutationObserver = callback => {
1457 if (!this._mutationObserver) {
1458 return;
1459 }
1460 callback(this._mutationObserver);
1461 };
1462 this._setFullScreenStyle = () => {
1463 const element = this.element;
1464 if (!element) {
1465 return;
1466 }
1467 const priority = "important",
1468 style = element.style;
1469 style.setProperty("position", "fixed", priority);
1470 style.setProperty("z-index", this.container.actualOptions.fullScreen.zIndex.toString(10), priority);
1471 style.setProperty("top", "0", priority);
1472 style.setProperty("left", "0", priority);
1473 style.setProperty("width", "100%", priority);
1474 style.setProperty("height", "100%", priority);
1475 };
1476 this.size = {
1477 height: 0,
1478 width: 0
1479 };
1480 this._context = null;
1481 this._generated = false;
1482 this._preDrawUpdaters = [];
1483 this._postDrawUpdaters = [];
1484 this._resizePlugins = [];
1485 this._colorPlugins = [];
1486 }
1487 get _fullScreen() {
1488 return this.container.actualOptions.fullScreen.enable;
1489 }
1490 clear() {
1491 const options = this.container.actualOptions,
1492 trail = options.particles.move.trail,
1493 trailFill = this._trailFill;
1494 if (options.backgroundMask.enable) {
1495 this.paint();
1496 } else if (trail.enable && trail.length > 0 && trailFill) {
1497 if (trailFill.color) {
1498 this._paintBase(getStyleFromRgb(trailFill.color, trailFill.opacity));
1499 } else if (trailFill.image) {
1500 this._paintImage(trailFill.image, trailFill.opacity);
1501 }
1502 } else {
1503 this.draw(ctx => {
1504 clear(ctx, this.size);
1505 });
1506 }
1507 }
1508 destroy() {
1509 this.stop();
1510 if (this._generated) {
1511 const element = this.element;
1512 element && element.remove();
1513 } else {
1514 this._resetOriginalStyle();
1515 }
1516 this._preDrawUpdaters = [];
1517 this._postDrawUpdaters = [];
1518 this._resizePlugins = [];
1519 this._colorPlugins = [];
1520 }
1521 draw(cb) {
1522 const ctx = this._context;
1523 if (!ctx) {
1524 return;
1525 }
1526 return cb(ctx);
1527 }
1528 drawParticle(particle, delta) {
1529 if (particle.spawning || particle.destroyed) {
1530 return;
1531 }
1532 const radius = particle.getRadius();
1533 if (radius <= 0) {
1534 return;
1535 }
1536 const pfColor = particle.getFillColor(),
1537 psColor = particle.getStrokeColor() ?? pfColor;
1538 let [fColor, sColor] = this._getPluginParticleColors(particle);
1539 if (!fColor) {
1540 fColor = pfColor;
1541 }
1542 if (!sColor) {
1543 sColor = psColor;
1544 }
1545 if (!fColor && !sColor) {
1546 return;
1547 }
1548 this.draw(ctx => {
1549 const container = this.container,
1550 options = container.actualOptions,
1551 zIndexOptions = particle.options.zIndex,
1552 zOpacityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.opacityRate,
1553 opacity = particle.bubble.opacity ?? particle.opacity?.value ?? 1,
1554 strokeOpacity = particle.strokeOpacity ?? opacity,
1555 zOpacity = opacity * zOpacityFactor,
1556 zStrokeOpacity = strokeOpacity * zOpacityFactor,
1557 transform = {},
1558 colorStyles = {
1559 fill: fColor ? getStyleFromHsl(fColor, zOpacity) : undefined
1560 };
1561 colorStyles.stroke = sColor ? getStyleFromHsl(sColor, zStrokeOpacity) : colorStyles.fill;
1562 this._applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform);
1563 drawParticle({
1564 container,
1565 context: ctx,
1566 particle,
1567 delta,
1568 colorStyles,
1569 backgroundMask: options.backgroundMask.enable,
1570 composite: options.backgroundMask.composite,
1571 radius: radius * (1 - particle.zIndexFactor) ** zIndexOptions.sizeRate,
1572 opacity: zOpacity,
1573 shadow: particle.options.shadow,
1574 transform
1575 });
1576 this._applyPostDrawUpdaters(particle);
1577 });
1578 }
1579 drawParticlePlugin(plugin, particle, delta) {
1580 this.draw(ctx => drawParticlePlugin(ctx, plugin, particle, delta));
1581 }
1582 drawPlugin(plugin, delta) {
1583 this.draw(ctx => drawPlugin(ctx, plugin, delta));
1584 }
1585 async init() {
1586 this._safeMutationObserver(obs => obs.disconnect());
1587 this._mutationObserver = safeMutationObserver(records => {
1588 for (const record of records) {
1589 if (record.type === "attributes" && record.attributeName === "style") {
1590 this._repairStyle();
1591 }
1592 }
1593 });
1594 this.resize();
1595 this._initStyle();
1596 this._initCover();
1597 try {
1598 await this._initTrail();
1599 } catch (e) {
1600 getLogger().error(e);
1601 }
1602 this.initBackground();
1603 this._safeMutationObserver(obs => {
1604 if (!this.element) {
1605 return;
1606 }
1607 obs.observe(this.element, {
1608 attributes: true
1609 });
1610 });
1611 this.initUpdaters();
1612 this.initPlugins();
1613 this.paint();
1614 }
1615 initBackground() {
1616 const options = this.container.actualOptions,
1617 background = options.background,
1618 element = this.element;
1619 if (!element) {
1620 return;
1621 }
1622 const elementStyle = element.style;
1623 if (!elementStyle) {
1624 return;
1625 }
1626 if (background.color) {
1627 const color = rangeColorToRgb(background.color);
1628 elementStyle.backgroundColor = color ? getStyleFromRgb(color, background.opacity) : "";
1629 } else {
1630 elementStyle.backgroundColor = "";
1631 }
1632 elementStyle.backgroundImage = background.image || "";
1633 elementStyle.backgroundPosition = background.position || "";
1634 elementStyle.backgroundRepeat = background.repeat || "";
1635 elementStyle.backgroundSize = background.size || "";
1636 }
1637 initPlugins() {
1638 this._resizePlugins = [];
1639 for (const [, plugin] of this.container.plugins) {
1640 if (plugin.resize) {
1641 this._resizePlugins.push(plugin);
1642 }
1643 if (plugin.particleFillColor || plugin.particleStrokeColor) {
1644 this._colorPlugins.push(plugin);
1645 }
1646 }
1647 }
1648 initUpdaters() {
1649 this._preDrawUpdaters = [];
1650 this._postDrawUpdaters = [];
1651 for (const updater of this.container.particles.updaters) {
1652 if (updater.afterDraw) {
1653 this._postDrawUpdaters.push(updater);
1654 }
1655 if (updater.getColorStyles || updater.getTransformValues || updater.beforeDraw) {
1656 this._preDrawUpdaters.push(updater);
1657 }
1658 }
1659 }
1660 loadCanvas(canvas) {
1661 if (this._generated && this.element) {
1662 this.element.remove();
1663 }
1664 this._generated = canvas.dataset && generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
1665 this.element = canvas;
1666 this.element.ariaHidden = "true";
1667 this._originalStyle = deepExtend({}, this.element.style);
1668 this.size.height = canvas.offsetHeight;
1669 this.size.width = canvas.offsetWidth;
1670 this._context = this.element.getContext("2d");
1671 this._safeMutationObserver(obs => {
1672 if (!this.element) {
1673 return;
1674 }
1675 obs.observe(this.element, {
1676 attributes: true
1677 });
1678 });
1679 this.container.retina.init();
1680 this.initBackground();
1681 }
1682 paint() {
1683 const options = this.container.actualOptions;
1684 this.draw(ctx => {
1685 if (options.backgroundMask.enable && options.backgroundMask.cover) {
1686 clear(ctx, this.size);
1687 this._paintBase(this._coverColorStyle);
1688 } else {
1689 this._paintBase();
1690 }
1691 });
1692 }
1693 resize() {
1694 if (!this.element) {
1695 return false;
1696 }
1697 const container = this.container,
1698 pxRatio = container.retina.pixelRatio,
1699 size = container.canvas.size,
1700 newSize = {
1701 width: this.element.offsetWidth * pxRatio,
1702 height: this.element.offsetHeight * pxRatio
1703 };
1704 if (newSize.height === size.height && newSize.width === size.width && newSize.height === this.element.height && newSize.width === this.element.width) {
1705 return false;
1706 }
1707 const oldSize = {
1708 ...size
1709 };
1710 this.element.width = size.width = this.element.offsetWidth * pxRatio;
1711 this.element.height = size.height = this.element.offsetHeight * pxRatio;
1712 if (this.container.started) {
1713 this.resizeFactor = {
1714 width: size.width / oldSize.width,
1715 height: size.height / oldSize.height
1716 };
1717 }
1718 return true;
1719 }
1720 stop() {
1721 this._safeMutationObserver(obs => obs.disconnect());
1722 this._mutationObserver = undefined;
1723 this.draw(ctx => clear(ctx, this.size));
1724 }
1725 async windowResize() {
1726 if (!this.element || !this.resize()) {
1727 return;
1728 }
1729 const container = this.container,
1730 needsRefresh = container.updateActualOptions();
1731 container.particles.setDensity();
1732 this._applyResizePlugins();
1733 if (needsRefresh) {
1734 await container.refresh();
1735 }
1736 }
1737}
1738;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/EventListeners.js
1739
1740
1741function manageListener(element, event, handler, add, options) {
1742 if (add) {
1743 let addOptions = {
1744 passive: true
1745 };
1746 if (isBoolean(options)) {
1747 addOptions.capture = options;
1748 } else if (options !== undefined) {
1749 addOptions = options;
1750 }
1751 element.addEventListener(event, handler, addOptions);
1752 } else {
1753 const removeOptions = options;
1754 element.removeEventListener(event, handler, removeOptions);
1755 }
1756}
1757class EventListeners {
1758 constructor(container) {
1759 this.container = container;
1760 this._doMouseTouchClick = e => {
1761 const container = this.container,
1762 options = container.actualOptions;
1763 if (this._canPush) {
1764 const mouseInteractivity = container.interactivity.mouse,
1765 mousePos = mouseInteractivity.position;
1766 if (!mousePos) {
1767 return;
1768 }
1769 mouseInteractivity.clickPosition = {
1770 ...mousePos
1771 };
1772 mouseInteractivity.clickTime = new Date().getTime();
1773 const onClick = options.interactivity.events.onClick;
1774 executeOnSingleOrMultiple(onClick.mode, mode => this.container.handleClickMode(mode));
1775 }
1776 if (e.type === "touchend") {
1777 setTimeout(() => this._mouseTouchFinish(), 500);
1778 }
1779 };
1780 this._handleThemeChange = e => {
1781 const mediaEvent = e,
1782 container = this.container,
1783 options = container.options,
1784 defaultThemes = options.defaultThemes,
1785 themeName = mediaEvent.matches ? defaultThemes.dark : defaultThemes.light,
1786 theme = options.themes.find(theme => theme.name === themeName);
1787 if (theme && theme.default.auto) {
1788 container.loadTheme(themeName);
1789 }
1790 };
1791 this._handleVisibilityChange = () => {
1792 const container = this.container,
1793 options = container.actualOptions;
1794 this._mouseTouchFinish();
1795 if (!options.pauseOnBlur) {
1796 return;
1797 }
1798 if (document && document.hidden) {
1799 container.pageHidden = true;
1800 container.pause();
1801 } else {
1802 container.pageHidden = false;
1803 if (container.getAnimationStatus()) {
1804 container.play(true);
1805 } else {
1806 container.draw(true);
1807 }
1808 }
1809 };
1810 this._handleWindowResize = async () => {
1811 if (this._resizeTimeout) {
1812 clearTimeout(this._resizeTimeout);
1813 delete this._resizeTimeout;
1814 }
1815 this._resizeTimeout = setTimeout(async () => {
1816 const canvas = this.container.canvas;
1817 canvas && (await canvas.windowResize());
1818 }, this.container.actualOptions.interactivity.events.resize.delay * 1000);
1819 };
1820 this._manageInteractivityListeners = (mouseLeaveTmpEvent, add) => {
1821 const handlers = this._handlers,
1822 container = this.container,
1823 options = container.actualOptions;
1824 const interactivityEl = container.interactivity.element;
1825 if (!interactivityEl) {
1826 return;
1827 }
1828 const html = interactivityEl,
1829 canvasEl = container.canvas.element;
1830 if (canvasEl) {
1831 canvasEl.style.pointerEvents = html === canvasEl ? "initial" : "none";
1832 }
1833 if (!(options.interactivity.events.onHover.enable || options.interactivity.events.onClick.enable)) {
1834 return;
1835 }
1836 manageListener(interactivityEl, mouseMoveEvent, handlers.mouseMove, add);
1837 manageListener(interactivityEl, touchStartEvent, handlers.touchStart, add);
1838 manageListener(interactivityEl, touchMoveEvent, handlers.touchMove, add);
1839 if (!options.interactivity.events.onClick.enable) {
1840 manageListener(interactivityEl, touchEndEvent, handlers.touchEnd, add);
1841 } else {
1842 manageListener(interactivityEl, touchEndEvent, handlers.touchEndClick, add);
1843 manageListener(interactivityEl, mouseUpEvent, handlers.mouseUp, add);
1844 manageListener(interactivityEl, mouseDownEvent, handlers.mouseDown, add);
1845 }
1846 manageListener(interactivityEl, mouseLeaveTmpEvent, handlers.mouseLeave, add);
1847 manageListener(interactivityEl, touchCancelEvent, handlers.touchCancel, add);
1848 };
1849 this._manageListeners = add => {
1850 const handlers = this._handlers,
1851 container = this.container,
1852 options = container.actualOptions,
1853 detectType = options.interactivity.detectsOn,
1854 canvasEl = container.canvas.element;
1855 let mouseLeaveTmpEvent = mouseLeaveEvent;
1856 if (detectType === "window") {
1857 container.interactivity.element = window;
1858 mouseLeaveTmpEvent = mouseOutEvent;
1859 } else if (detectType === "parent" && canvasEl) {
1860 container.interactivity.element = canvasEl.parentElement ?? canvasEl.parentNode;
1861 } else {
1862 container.interactivity.element = canvasEl;
1863 }
1864 this._manageMediaMatch(add);
1865 this._manageResize(add);
1866 this._manageInteractivityListeners(mouseLeaveTmpEvent, add);
1867 if (document) {
1868 manageListener(document, visibilityChangeEvent, handlers.visibilityChange, add, false);
1869 }
1870 };
1871 this._manageMediaMatch = add => {
1872 const handlers = this._handlers,
1873 mediaMatch = safeMatchMedia("(prefers-color-scheme: dark)");
1874 if (!mediaMatch) {
1875 return;
1876 }
1877 if (mediaMatch.addEventListener !== undefined) {
1878 manageListener(mediaMatch, "change", handlers.themeChange, add);
1879 return;
1880 }
1881 if (mediaMatch.addListener === undefined) {
1882 return;
1883 }
1884 if (add) {
1885 mediaMatch.addListener(handlers.oldThemeChange);
1886 } else {
1887 mediaMatch.removeListener(handlers.oldThemeChange);
1888 }
1889 };
1890 this._manageResize = add => {
1891 const handlers = this._handlers,
1892 container = this.container,
1893 options = container.actualOptions;
1894 if (!options.interactivity.events.resize) {
1895 return;
1896 }
1897 if (typeof ResizeObserver === "undefined") {
1898 manageListener(window, resizeEvent, handlers.resize, add);
1899 return;
1900 }
1901 const canvasEl = container.canvas.element;
1902 if (this._resizeObserver && !add) {
1903 if (canvasEl) {
1904 this._resizeObserver.unobserve(canvasEl);
1905 }
1906 this._resizeObserver.disconnect();
1907 delete this._resizeObserver;
1908 } else if (!this._resizeObserver && add && canvasEl) {
1909 this._resizeObserver = new ResizeObserver(async entries => {
1910 const entry = entries.find(e => e.target === canvasEl);
1911 if (!entry) {
1912 return;
1913 }
1914 await this._handleWindowResize();
1915 });
1916 this._resizeObserver.observe(canvasEl);
1917 }
1918 };
1919 this._mouseDown = () => {
1920 const {
1921 interactivity
1922 } = this.container;
1923 if (!interactivity) {
1924 return;
1925 }
1926 const {
1927 mouse
1928 } = interactivity;
1929 mouse.clicking = true;
1930 mouse.downPosition = mouse.position;
1931 };
1932 this._mouseTouchClick = e => {
1933 const container = this.container,
1934 options = container.actualOptions,
1935 {
1936 mouse
1937 } = container.interactivity;
1938 mouse.inside = true;
1939 let handled = false;
1940 const mousePosition = mouse.position;
1941 if (!mousePosition || !options.interactivity.events.onClick.enable) {
1942 return;
1943 }
1944 for (const [, plugin] of container.plugins) {
1945 if (!plugin.clickPositionValid) {
1946 continue;
1947 }
1948 handled = plugin.clickPositionValid(mousePosition);
1949 if (handled) {
1950 break;
1951 }
1952 }
1953 if (!handled) {
1954 this._doMouseTouchClick(e);
1955 }
1956 mouse.clicking = false;
1957 };
1958 this._mouseTouchFinish = () => {
1959 const interactivity = this.container.interactivity;
1960 if (!interactivity) {
1961 return;
1962 }
1963 const mouse = interactivity.mouse;
1964 delete mouse.position;
1965 delete mouse.clickPosition;
1966 delete mouse.downPosition;
1967 interactivity.status = mouseLeaveEvent;
1968 mouse.inside = false;
1969 mouse.clicking = false;
1970 };
1971 this._mouseTouchMove = e => {
1972 const container = this.container,
1973 options = container.actualOptions,
1974 interactivity = container.interactivity,
1975 canvasEl = container.canvas.element;
1976 if (!interactivity || !interactivity.element) {
1977 return;
1978 }
1979 interactivity.mouse.inside = true;
1980 let pos;
1981 if (e.type.startsWith("pointer")) {
1982 this._canPush = true;
1983 const mouseEvent = e;
1984 if (interactivity.element === window) {
1985 if (canvasEl) {
1986 const clientRect = canvasEl.getBoundingClientRect();
1987 pos = {
1988 x: mouseEvent.clientX - clientRect.left,
1989 y: mouseEvent.clientY - clientRect.top
1990 };
1991 }
1992 } else if (options.interactivity.detectsOn === "parent") {
1993 const source = mouseEvent.target,
1994 target = mouseEvent.currentTarget;
1995 if (source && target && canvasEl) {
1996 const sourceRect = source.getBoundingClientRect(),
1997 targetRect = target.getBoundingClientRect(),
1998 canvasRect = canvasEl.getBoundingClientRect();
1999 pos = {
2000 x: mouseEvent.offsetX + 2 * sourceRect.left - (targetRect.left + canvasRect.left),
2001 y: mouseEvent.offsetY + 2 * sourceRect.top - (targetRect.top + canvasRect.top)
2002 };
2003 } else {
2004 pos = {
2005 x: mouseEvent.offsetX ?? mouseEvent.clientX,
2006 y: mouseEvent.offsetY ?? mouseEvent.clientY
2007 };
2008 }
2009 } else if (mouseEvent.target === canvasEl) {
2010 pos = {
2011 x: mouseEvent.offsetX ?? mouseEvent.clientX,
2012 y: mouseEvent.offsetY ?? mouseEvent.clientY
2013 };
2014 }
2015 } else {
2016 this._canPush = e.type !== "touchmove";
2017 if (canvasEl) {
2018 const touchEvent = e,
2019 lastTouch = touchEvent.touches[touchEvent.touches.length - 1],
2020 canvasRect = canvasEl.getBoundingClientRect();
2021 pos = {
2022 x: lastTouch.clientX - (canvasRect.left ?? 0),
2023 y: lastTouch.clientY - (canvasRect.top ?? 0)
2024 };
2025 }
2026 }
2027 const pxRatio = container.retina.pixelRatio;
2028 if (pos) {
2029 pos.x *= pxRatio;
2030 pos.y *= pxRatio;
2031 }
2032 interactivity.mouse.position = pos;
2033 interactivity.status = mouseMoveEvent;
2034 };
2035 this._touchEnd = e => {
2036 const evt = e,
2037 touches = Array.from(evt.changedTouches);
2038 for (const touch of touches) {
2039 this._touches.delete(touch.identifier);
2040 }
2041 this._mouseTouchFinish();
2042 };
2043 this._touchEndClick = e => {
2044 const evt = e,
2045 touches = Array.from(evt.changedTouches);
2046 for (const touch of touches) {
2047 this._touches.delete(touch.identifier);
2048 }
2049 this._mouseTouchClick(e);
2050 };
2051 this._touchStart = e => {
2052 const evt = e,
2053 touches = Array.from(evt.changedTouches);
2054 for (const touch of touches) {
2055 this._touches.set(touch.identifier, performance.now());
2056 }
2057 this._mouseTouchMove(e);
2058 };
2059 this._canPush = true;
2060 this._touches = new Map();
2061 this._handlers = {
2062 mouseDown: () => this._mouseDown(),
2063 mouseLeave: () => this._mouseTouchFinish(),
2064 mouseMove: e => this._mouseTouchMove(e),
2065 mouseUp: e => this._mouseTouchClick(e),
2066 touchStart: e => this._touchStart(e),
2067 touchMove: e => this._mouseTouchMove(e),
2068 touchEnd: e => this._touchEnd(e),
2069 touchCancel: e => this._touchEnd(e),
2070 touchEndClick: e => this._touchEndClick(e),
2071 visibilityChange: () => this._handleVisibilityChange(),
2072 themeChange: e => this._handleThemeChange(e),
2073 oldThemeChange: e => this._handleThemeChange(e),
2074 resize: () => {
2075 this._handleWindowResize();
2076 }
2077 };
2078 }
2079 addListeners() {
2080 this._manageListeners(true);
2081 }
2082 removeListeners() {
2083 this._manageListeners(false);
2084 }
2085}
2086;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/OptionsColor.js
2087
2088class OptionsColor {
2089 constructor() {
2090 this.value = "";
2091 }
2092 static create(source, data) {
2093 const color = new OptionsColor();
2094 color.load(source);
2095 if (data !== undefined) {
2096 if (isString(data) || isArray(data)) {
2097 color.load({
2098 value: data
2099 });
2100 } else {
2101 color.load(data);
2102 }
2103 }
2104 return color;
2105 }
2106 load(data) {
2107 if (data?.value === undefined) {
2108 return;
2109 }
2110 this.value = data.value;
2111 }
2112}
2113;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Background/Background.js
2114
2115class Background {
2116 constructor() {
2117 this.color = new OptionsColor();
2118 this.color.value = "";
2119 this.image = "";
2120 this.position = "";
2121 this.repeat = "";
2122 this.size = "";
2123 this.opacity = 1;
2124 }
2125 load(data) {
2126 if (!data) {
2127 return;
2128 }
2129 if (data.color !== undefined) {
2130 this.color = OptionsColor.create(this.color, data.color);
2131 }
2132 if (data.image !== undefined) {
2133 this.image = data.image;
2134 }
2135 if (data.position !== undefined) {
2136 this.position = data.position;
2137 }
2138 if (data.repeat !== undefined) {
2139 this.repeat = data.repeat;
2140 }
2141 if (data.size !== undefined) {
2142 this.size = data.size;
2143 }
2144 if (data.opacity !== undefined) {
2145 this.opacity = data.opacity;
2146 }
2147 }
2148}
2149;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/BackgroundMask/BackgroundMaskCover.js
2150
2151class BackgroundMaskCover {
2152 constructor() {
2153 this.color = new OptionsColor();
2154 this.color.value = "#fff";
2155 this.opacity = 1;
2156 }
2157 load(data) {
2158 if (!data) {
2159 return;
2160 }
2161 if (data.color !== undefined) {
2162 this.color = OptionsColor.create(this.color, data.color);
2163 }
2164 if (data.opacity !== undefined) {
2165 this.opacity = data.opacity;
2166 }
2167 }
2168}
2169;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/BackgroundMask/BackgroundMask.js
2170
2171
2172class BackgroundMask {
2173 constructor() {
2174 this.composite = "destination-out";
2175 this.cover = new BackgroundMaskCover();
2176 this.enable = false;
2177 }
2178 load(data) {
2179 if (!data) {
2180 return;
2181 }
2182 if (data.composite !== undefined) {
2183 this.composite = data.composite;
2184 }
2185 if (data.cover !== undefined) {
2186 const cover = data.cover;
2187 const color = isString(data.cover) ? {
2188 color: data.cover
2189 } : data.cover;
2190 this.cover.load(cover.color !== undefined ? cover : {
2191 color: color
2192 });
2193 }
2194 if (data.enable !== undefined) {
2195 this.enable = data.enable;
2196 }
2197 }
2198}
2199;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/FullScreen/FullScreen.js
2200class FullScreen {
2201 constructor() {
2202 this.enable = true;
2203 this.zIndex = 0;
2204 }
2205 load(data) {
2206 if (!data) {
2207 return;
2208 }
2209 if (data.enable !== undefined) {
2210 this.enable = data.enable;
2211 }
2212 if (data.zIndex !== undefined) {
2213 this.zIndex = data.zIndex;
2214 }
2215 }
2216}
2217;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Events/ClickEvent.js
2218class ClickEvent {
2219 constructor() {
2220 this.enable = false;
2221 this.mode = [];
2222 }
2223 load(data) {
2224 if (!data) {
2225 return;
2226 }
2227 if (data.enable !== undefined) {
2228 this.enable = data.enable;
2229 }
2230 if (data.mode !== undefined) {
2231 this.mode = data.mode;
2232 }
2233 }
2234}
2235;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Events/DivEvent.js
2236
2237class DivEvent {
2238 constructor() {
2239 this.selectors = [];
2240 this.enable = false;
2241 this.mode = [];
2242 this.type = "circle";
2243 }
2244 get el() {
2245 return this.elementId;
2246 }
2247 set el(value) {
2248 this.elementId = value;
2249 }
2250 get elementId() {
2251 return this.ids;
2252 }
2253 set elementId(value) {
2254 this.ids = value;
2255 }
2256 get ids() {
2257 return executeOnSingleOrMultiple(this.selectors, t => t.replace("#", ""));
2258 }
2259 set ids(value) {
2260 this.selectors = executeOnSingleOrMultiple(value, t => `#${t}`);
2261 }
2262 load(data) {
2263 if (!data) {
2264 return;
2265 }
2266 const ids = data.ids ?? data.elementId ?? data.el;
2267 if (ids !== undefined) {
2268 this.ids = ids;
2269 }
2270 if (data.selectors !== undefined) {
2271 this.selectors = data.selectors;
2272 }
2273 if (data.enable !== undefined) {
2274 this.enable = data.enable;
2275 }
2276 if (data.mode !== undefined) {
2277 this.mode = data.mode;
2278 }
2279 if (data.type !== undefined) {
2280 this.type = data.type;
2281 }
2282 }
2283}
2284;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Events/Parallax.js
2285class Parallax {
2286 constructor() {
2287 this.enable = false;
2288 this.force = 2;
2289 this.smooth = 10;
2290 }
2291 load(data) {
2292 if (!data) {
2293 return;
2294 }
2295 if (data.enable !== undefined) {
2296 this.enable = data.enable;
2297 }
2298 if (data.force !== undefined) {
2299 this.force = data.force;
2300 }
2301 if (data.smooth !== undefined) {
2302 this.smooth = data.smooth;
2303 }
2304 }
2305}
2306;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Events/HoverEvent.js
2307
2308class HoverEvent {
2309 constructor() {
2310 this.enable = false;
2311 this.mode = [];
2312 this.parallax = new Parallax();
2313 }
2314 load(data) {
2315 if (!data) {
2316 return;
2317 }
2318 if (data.enable !== undefined) {
2319 this.enable = data.enable;
2320 }
2321 if (data.mode !== undefined) {
2322 this.mode = data.mode;
2323 }
2324 this.parallax.load(data.parallax);
2325 }
2326}
2327;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Events/ResizeEvent.js
2328class ResizeEvent {
2329 constructor() {
2330 this.delay = 0.5;
2331 this.enable = true;
2332 }
2333 load(data) {
2334 if (data === undefined) {
2335 return;
2336 }
2337 if (data.delay !== undefined) {
2338 this.delay = data.delay;
2339 }
2340 if (data.enable !== undefined) {
2341 this.enable = data.enable;
2342 }
2343 }
2344}
2345;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Events/Events.js
2346
2347
2348
2349
2350
2351class Events {
2352 constructor() {
2353 this.onClick = new ClickEvent();
2354 this.onDiv = new DivEvent();
2355 this.onHover = new HoverEvent();
2356 this.resize = new ResizeEvent();
2357 }
2358 get onclick() {
2359 return this.onClick;
2360 }
2361 set onclick(value) {
2362 this.onClick = value;
2363 }
2364 get ondiv() {
2365 return this.onDiv;
2366 }
2367 set ondiv(value) {
2368 this.onDiv = value;
2369 }
2370 get onhover() {
2371 return this.onHover;
2372 }
2373 set onhover(value) {
2374 this.onHover = value;
2375 }
2376 load(data) {
2377 if (!data) {
2378 return;
2379 }
2380 this.onClick.load(data.onClick ?? data.onclick);
2381 const onDiv = data.onDiv ?? data.ondiv;
2382 if (onDiv !== undefined) {
2383 this.onDiv = executeOnSingleOrMultiple(onDiv, t => {
2384 const tmp = new DivEvent();
2385 tmp.load(t);
2386 return tmp;
2387 });
2388 }
2389 this.onHover.load(data.onHover ?? data.onhover);
2390 if (isBoolean(data.resize)) {
2391 this.resize.enable = data.resize;
2392 } else {
2393 this.resize.load(data.resize);
2394 }
2395 }
2396}
2397;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Modes/Modes.js
2398class Modes {
2399 constructor(engine, container) {
2400 this._engine = engine;
2401 this._container = container;
2402 }
2403 load(data) {
2404 if (!data) {
2405 return;
2406 }
2407 if (!this._container) {
2408 return;
2409 }
2410 const interactors = this._engine.plugins.interactors.get(this._container);
2411 if (!interactors) {
2412 return;
2413 }
2414 for (const interactor of interactors) {
2415 if (!interactor.loadModeOptions) {
2416 continue;
2417 }
2418 interactor.loadModeOptions(this, data);
2419 }
2420 }
2421}
2422;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Interactivity/Interactivity.js
2423
2424
2425class Interactivity {
2426 constructor(engine, container) {
2427 this.detectsOn = "window";
2428 this.events = new Events();
2429 this.modes = new Modes(engine, container);
2430 }
2431 get detect_on() {
2432 return this.detectsOn;
2433 }
2434 set detect_on(value) {
2435 this.detectsOn = value;
2436 }
2437 load(data) {
2438 if (!data) {
2439 return;
2440 }
2441 const detectsOn = data.detectsOn ?? data.detect_on;
2442 if (detectsOn !== undefined) {
2443 this.detectsOn = detectsOn;
2444 }
2445 this.events.load(data.events);
2446 this.modes.load(data.modes);
2447 }
2448}
2449;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/ManualParticle.js
2450
2451class ManualParticle {
2452 load(data) {
2453 if (!data) {
2454 return;
2455 }
2456 if (data.position) {
2457 this.position = {
2458 x: data.position.x ?? 50,
2459 y: data.position.y ?? 50,
2460 mode: data.position.mode ?? "percent"
2461 };
2462 }
2463 if (data.options) {
2464 this.options = deepExtend({}, data.options);
2465 }
2466 }
2467}
2468;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Responsive.js
2469
2470class Responsive {
2471 constructor() {
2472 this.maxWidth = Infinity;
2473 this.options = {};
2474 this.mode = "canvas";
2475 }
2476 load(data) {
2477 if (!data) {
2478 return;
2479 }
2480 if (data.maxWidth !== undefined) {
2481 this.maxWidth = data.maxWidth;
2482 }
2483 if (data.mode !== undefined) {
2484 if (data.mode === "screen") {
2485 this.mode = "screen";
2486 } else {
2487 this.mode = "canvas";
2488 }
2489 }
2490 if (data.options !== undefined) {
2491 this.options = deepExtend({}, data.options);
2492 }
2493 }
2494}
2495;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Theme/ThemeDefault.js
2496class ThemeDefault {
2497 constructor() {
2498 this.auto = false;
2499 this.mode = "any";
2500 this.value = false;
2501 }
2502 load(data) {
2503 if (!data) {
2504 return;
2505 }
2506 if (data.auto !== undefined) {
2507 this.auto = data.auto;
2508 }
2509 if (data.mode !== undefined) {
2510 this.mode = data.mode;
2511 }
2512 if (data.value !== undefined) {
2513 this.value = data.value;
2514 }
2515 }
2516}
2517;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Theme/Theme.js
2518
2519
2520class Theme {
2521 constructor() {
2522 this.name = "";
2523 this.default = new ThemeDefault();
2524 }
2525 load(data) {
2526 if (!data) {
2527 return;
2528 }
2529 if (data.name !== undefined) {
2530 this.name = data.name;
2531 }
2532 this.default.load(data.default);
2533 if (data.options !== undefined) {
2534 this.options = deepExtend({}, data.options);
2535 }
2536 }
2537}
2538;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/ColorAnimation.js
2539
2540class ColorAnimation {
2541 constructor() {
2542 this.count = 0;
2543 this.enable = false;
2544 this.offset = 0;
2545 this.speed = 1;
2546 this.delay = 0;
2547 this.decay = 0;
2548 this.sync = true;
2549 }
2550 load(data) {
2551 if (!data) {
2552 return;
2553 }
2554 if (data.count !== undefined) {
2555 this.count = setRangeValue(data.count);
2556 }
2557 if (data.enable !== undefined) {
2558 this.enable = data.enable;
2559 }
2560 if (data.offset !== undefined) {
2561 this.offset = setRangeValue(data.offset);
2562 }
2563 if (data.speed !== undefined) {
2564 this.speed = setRangeValue(data.speed);
2565 }
2566 if (data.decay !== undefined) {
2567 this.decay = setRangeValue(data.decay);
2568 }
2569 if (data.delay !== undefined) {
2570 this.delay = setRangeValue(data.delay);
2571 }
2572 if (data.sync !== undefined) {
2573 this.sync = data.sync;
2574 }
2575 }
2576}
2577;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/HslAnimation.js
2578
2579class HslAnimation {
2580 constructor() {
2581 this.h = new ColorAnimation();
2582 this.s = new ColorAnimation();
2583 this.l = new ColorAnimation();
2584 }
2585 load(data) {
2586 if (!data) {
2587 return;
2588 }
2589 this.h.load(data.h);
2590 this.s.load(data.s);
2591 this.l.load(data.l);
2592 }
2593}
2594;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/AnimatableColor.js
2595
2596
2597
2598class AnimatableColor extends OptionsColor {
2599 constructor() {
2600 super();
2601 this.animation = new HslAnimation();
2602 }
2603 static create(source, data) {
2604 const color = new AnimatableColor();
2605 color.load(source);
2606 if (data !== undefined) {
2607 if (isString(data) || isArray(data)) {
2608 color.load({
2609 value: data
2610 });
2611 } else {
2612 color.load(data);
2613 }
2614 }
2615 return color;
2616 }
2617 load(data) {
2618 super.load(data);
2619 if (!data) {
2620 return;
2621 }
2622 const colorAnimation = data.animation;
2623 if (colorAnimation !== undefined) {
2624 if (colorAnimation.enable !== undefined) {
2625 this.animation.h.load(colorAnimation);
2626 } else {
2627 this.animation.load(data.animation);
2628 }
2629 }
2630 }
2631}
2632;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Collisions/CollisionsAbsorb.js
2633class CollisionsAbsorb {
2634 constructor() {
2635 this.speed = 2;
2636 }
2637 load(data) {
2638 if (!data) {
2639 return;
2640 }
2641 if (data.speed !== undefined) {
2642 this.speed = data.speed;
2643 }
2644 }
2645}
2646;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Collisions/CollisionsOverlap.js
2647class CollisionsOverlap {
2648 constructor() {
2649 this.enable = true;
2650 this.retries = 0;
2651 }
2652 load(data) {
2653 if (!data) {
2654 return;
2655 }
2656 if (data.enable !== undefined) {
2657 this.enable = data.enable;
2658 }
2659 if (data.retries !== undefined) {
2660 this.retries = data.retries;
2661 }
2662 }
2663}
2664;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/AnimationOptions.js
2665
2666class AnimationOptions {
2667 constructor() {
2668 this.count = 0;
2669 this.enable = false;
2670 this.speed = 1;
2671 this.decay = 0;
2672 this.delay = 0;
2673 this.sync = false;
2674 }
2675 load(data) {
2676 if (!data) {
2677 return;
2678 }
2679 if (data.count !== undefined) {
2680 this.count = setRangeValue(data.count);
2681 }
2682 if (data.enable !== undefined) {
2683 this.enable = data.enable;
2684 }
2685 if (data.speed !== undefined) {
2686 this.speed = setRangeValue(data.speed);
2687 }
2688 if (data.decay !== undefined) {
2689 this.decay = setRangeValue(data.decay);
2690 }
2691 if (data.delay !== undefined) {
2692 this.delay = setRangeValue(data.delay);
2693 }
2694 if (data.sync !== undefined) {
2695 this.sync = data.sync;
2696 }
2697 }
2698}
2699class RangedAnimationOptions extends AnimationOptions {
2700 constructor() {
2701 super();
2702 this.mode = "auto";
2703 this.startValue = "random";
2704 }
2705 load(data) {
2706 super.load(data);
2707 if (!data) {
2708 return;
2709 }
2710 if (data.minimumValue !== undefined) {
2711 this.minimumValue = data.minimumValue;
2712 }
2713 if (data.mode !== undefined) {
2714 this.mode = data.mode;
2715 }
2716 if (data.startValue !== undefined) {
2717 this.startValue = data.startValue;
2718 }
2719 }
2720}
2721;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Random.js
2722class Random {
2723 constructor() {
2724 this.enable = false;
2725 this.minimumValue = 0;
2726 }
2727 load(data) {
2728 if (!data) {
2729 return;
2730 }
2731 if (data.enable !== undefined) {
2732 this.enable = data.enable;
2733 }
2734 if (data.minimumValue !== undefined) {
2735 this.minimumValue = data.minimumValue;
2736 }
2737 }
2738}
2739;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/ValueWithRandom.js
2740
2741
2742
2743
2744class ValueWithRandom {
2745 constructor() {
2746 this.random = new Random();
2747 this.value = 0;
2748 }
2749 load(data) {
2750 if (!data) {
2751 return;
2752 }
2753 if (isBoolean(data.random)) {
2754 this.random.enable = data.random;
2755 } else {
2756 this.random.load(data.random);
2757 }
2758 if (data.value !== undefined) {
2759 this.value = setRangeValue(data.value, this.random.enable ? this.random.minimumValue : undefined);
2760 }
2761 }
2762}
2763class AnimationValueWithRandom extends ValueWithRandom {
2764 constructor() {
2765 super();
2766 this.animation = new AnimationOptions();
2767 }
2768 get anim() {
2769 return this.animation;
2770 }
2771 set anim(value) {
2772 this.animation = value;
2773 }
2774 load(data) {
2775 super.load(data);
2776 if (!data) {
2777 return;
2778 }
2779 const animation = data.animation ?? data.anim;
2780 if (animation !== undefined) {
2781 this.animation.load(animation);
2782 }
2783 }
2784}
2785class RangedAnimationValueWithRandom extends AnimationValueWithRandom {
2786 constructor() {
2787 super();
2788 this.animation = new RangedAnimationOptions();
2789 }
2790 load(data) {
2791 super.load(data);
2792 if (!data) {
2793 return;
2794 }
2795 const animation = data.animation ?? data.anim;
2796 if (animation !== undefined) {
2797 this.value = setRangeValue(this.value, this.animation.enable ? this.animation.minimumValue : undefined);
2798 }
2799 }
2800}
2801;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Bounce/ParticlesBounceFactor.js
2802
2803class ParticlesBounceFactor extends ValueWithRandom {
2804 constructor() {
2805 super();
2806 this.random.minimumValue = 0.1;
2807 this.value = 1;
2808 }
2809}
2810;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Bounce/ParticlesBounce.js
2811
2812class ParticlesBounce {
2813 constructor() {
2814 this.horizontal = new ParticlesBounceFactor();
2815 this.vertical = new ParticlesBounceFactor();
2816 }
2817 load(data) {
2818 if (!data) {
2819 return;
2820 }
2821 this.horizontal.load(data.horizontal);
2822 this.vertical.load(data.vertical);
2823 }
2824}
2825;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Collisions/Collisions.js
2826
2827
2828
2829
2830class Collisions {
2831 constructor() {
2832 this.absorb = new CollisionsAbsorb();
2833 this.bounce = new ParticlesBounce();
2834 this.enable = false;
2835 this.maxSpeed = 50;
2836 this.mode = "bounce";
2837 this.overlap = new CollisionsOverlap();
2838 }
2839 load(data) {
2840 if (!data) {
2841 return;
2842 }
2843 this.absorb.load(data.absorb);
2844 this.bounce.load(data.bounce);
2845 if (data.enable !== undefined) {
2846 this.enable = data.enable;
2847 }
2848 if (data.maxSpeed !== undefined) {
2849 this.maxSpeed = setRangeValue(data.maxSpeed);
2850 }
2851 if (data.mode !== undefined) {
2852 this.mode = data.mode;
2853 }
2854 this.overlap.load(data.overlap);
2855 }
2856}
2857;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/MoveAngle.js
2858
2859class MoveAngle {
2860 constructor() {
2861 this.offset = 0;
2862 this.value = 90;
2863 }
2864 load(data) {
2865 if (!data) {
2866 return;
2867 }
2868 if (data.offset !== undefined) {
2869 this.offset = setRangeValue(data.offset);
2870 }
2871 if (data.value !== undefined) {
2872 this.value = setRangeValue(data.value);
2873 }
2874 }
2875}
2876;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/MoveAttract.js
2877
2878class MoveAttract {
2879 constructor() {
2880 this.distance = 200;
2881 this.enable = false;
2882 this.rotate = {
2883 x: 3000,
2884 y: 3000
2885 };
2886 }
2887 get rotateX() {
2888 return this.rotate.x;
2889 }
2890 set rotateX(value) {
2891 this.rotate.x = value;
2892 }
2893 get rotateY() {
2894 return this.rotate.y;
2895 }
2896 set rotateY(value) {
2897 this.rotate.y = value;
2898 }
2899 load(data) {
2900 if (!data) {
2901 return;
2902 }
2903 if (data.distance !== undefined) {
2904 this.distance = setRangeValue(data.distance);
2905 }
2906 if (data.enable !== undefined) {
2907 this.enable = data.enable;
2908 }
2909 const rotateX = data.rotate?.x ?? data.rotateX;
2910 if (rotateX !== undefined) {
2911 this.rotate.x = rotateX;
2912 }
2913 const rotateY = data.rotate?.y ?? data.rotateY;
2914 if (rotateY !== undefined) {
2915 this.rotate.y = rotateY;
2916 }
2917 }
2918}
2919;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/MoveCenter.js
2920class MoveCenter {
2921 constructor() {
2922 this.x = 50;
2923 this.y = 50;
2924 this.mode = "percent";
2925 this.radius = 0;
2926 }
2927 load(data) {
2928 if (!data) {
2929 return;
2930 }
2931 if (data.x !== undefined) {
2932 this.x = data.x;
2933 }
2934 if (data.y !== undefined) {
2935 this.y = data.y;
2936 }
2937 if (data.mode !== undefined) {
2938 this.mode = data.mode;
2939 }
2940 if (data.radius !== undefined) {
2941 this.radius = data.radius;
2942 }
2943 }
2944}
2945;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/MoveGravity.js
2946
2947class MoveGravity {
2948 constructor() {
2949 this.acceleration = 9.81;
2950 this.enable = false;
2951 this.inverse = false;
2952 this.maxSpeed = 50;
2953 }
2954 load(data) {
2955 if (!data) {
2956 return;
2957 }
2958 if (data.acceleration !== undefined) {
2959 this.acceleration = setRangeValue(data.acceleration);
2960 }
2961 if (data.enable !== undefined) {
2962 this.enable = data.enable;
2963 }
2964 if (data.inverse !== undefined) {
2965 this.inverse = data.inverse;
2966 }
2967 if (data.maxSpeed !== undefined) {
2968 this.maxSpeed = setRangeValue(data.maxSpeed);
2969 }
2970 }
2971}
2972;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/Path/MovePath.js
2973
2974
2975class MovePath {
2976 constructor() {
2977 this.clamp = true;
2978 this.delay = new ValueWithRandom();
2979 this.enable = false;
2980 this.options = {};
2981 }
2982 load(data) {
2983 if (!data) {
2984 return;
2985 }
2986 if (data.clamp !== undefined) {
2987 this.clamp = data.clamp;
2988 }
2989 this.delay.load(data.delay);
2990 if (data.enable !== undefined) {
2991 this.enable = data.enable;
2992 }
2993 this.generator = data.generator;
2994 if (data.options) {
2995 this.options = deepExtend(this.options, data.options);
2996 }
2997 }
2998}
2999;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/MoveTrailFill.js
3000
3001class MoveTrailFill {
3002 load(data) {
3003 if (!data) {
3004 return;
3005 }
3006 if (data.color !== undefined) {
3007 this.color = OptionsColor.create(this.color, data.color);
3008 }
3009 if (data.image !== undefined) {
3010 this.image = data.image;
3011 }
3012 }
3013}
3014;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/MoveTrail.js
3015
3016class MoveTrail {
3017 constructor() {
3018 this.enable = false;
3019 this.length = 10;
3020 this.fill = new MoveTrailFill();
3021 }
3022 get fillColor() {
3023 return this.fill.color;
3024 }
3025 set fillColor(value) {
3026 this.fill.load({
3027 color: value
3028 });
3029 }
3030 load(data) {
3031 if (!data) {
3032 return;
3033 }
3034 if (data.enable !== undefined) {
3035 this.enable = data.enable;
3036 }
3037 if (data.fill !== undefined || data.fillColor !== undefined) {
3038 this.fill.load(data.fill || {
3039 color: data.fillColor
3040 });
3041 }
3042 if (data.length !== undefined) {
3043 this.length = data.length;
3044 }
3045 }
3046}
3047;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/OutModes.js
3048class OutModes {
3049 constructor() {
3050 this.default = "out";
3051 }
3052 load(data) {
3053 if (!data) {
3054 return;
3055 }
3056 if (data.default !== undefined) {
3057 this.default = data.default;
3058 }
3059 this.bottom = data.bottom ?? data.default;
3060 this.left = data.left ?? data.default;
3061 this.right = data.right ?? data.default;
3062 this.top = data.top ?? data.default;
3063 }
3064}
3065;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/Spin.js
3066
3067
3068class Spin {
3069 constructor() {
3070 this.acceleration = 0;
3071 this.enable = false;
3072 }
3073 load(data) {
3074 if (!data) {
3075 return;
3076 }
3077 if (data.acceleration !== undefined) {
3078 this.acceleration = setRangeValue(data.acceleration);
3079 }
3080 if (data.enable !== undefined) {
3081 this.enable = data.enable;
3082 }
3083 if (data.position) {
3084 this.position = deepExtend({}, data.position);
3085 }
3086 }
3087}
3088;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Move/Move.js
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099class Move {
3100 constructor() {
3101 this.angle = new MoveAngle();
3102 this.attract = new MoveAttract();
3103 this.center = new MoveCenter();
3104 this.decay = 0;
3105 this.distance = {};
3106 this.direction = "none";
3107 this.drift = 0;
3108 this.enable = false;
3109 this.gravity = new MoveGravity();
3110 this.path = new MovePath();
3111 this.outModes = new OutModes();
3112 this.random = false;
3113 this.size = false;
3114 this.speed = 2;
3115 this.spin = new Spin();
3116 this.straight = false;
3117 this.trail = new MoveTrail();
3118 this.vibrate = false;
3119 this.warp = false;
3120 }
3121 get bounce() {
3122 return this.collisions;
3123 }
3124 set bounce(value) {
3125 this.collisions = value;
3126 }
3127 get collisions() {
3128 return false;
3129 }
3130 set collisions(_) {}
3131 get noise() {
3132 return this.path;
3133 }
3134 set noise(value) {
3135 this.path = value;
3136 }
3137 get outMode() {
3138 return this.outModes.default;
3139 }
3140 set outMode(value) {
3141 this.outModes.default = value;
3142 }
3143 get out_mode() {
3144 return this.outMode;
3145 }
3146 set out_mode(value) {
3147 this.outMode = value;
3148 }
3149 load(data) {
3150 if (!data) {
3151 return;
3152 }
3153 this.angle.load(isNumber(data.angle) ? {
3154 value: data.angle
3155 } : data.angle);
3156 this.attract.load(data.attract);
3157 this.center.load(data.center);
3158 if (data.decay !== undefined) {
3159 this.decay = setRangeValue(data.decay);
3160 }
3161 if (data.direction !== undefined) {
3162 this.direction = data.direction;
3163 }
3164 if (data.distance !== undefined) {
3165 this.distance = isNumber(data.distance) ? {
3166 horizontal: data.distance,
3167 vertical: data.distance
3168 } : {
3169 ...data.distance
3170 };
3171 }
3172 if (data.drift !== undefined) {
3173 this.drift = setRangeValue(data.drift);
3174 }
3175 if (data.enable !== undefined) {
3176 this.enable = data.enable;
3177 }
3178 this.gravity.load(data.gravity);
3179 const outModes = data.outModes ?? data.outMode ?? data.out_mode;
3180 if (outModes !== undefined) {
3181 if (isObject(outModes)) {
3182 this.outModes.load(outModes);
3183 } else {
3184 this.outModes.load({
3185 default: outModes
3186 });
3187 }
3188 }
3189 this.path.load(data.path ?? data.noise);
3190 if (data.random !== undefined) {
3191 this.random = data.random;
3192 }
3193 if (data.size !== undefined) {
3194 this.size = data.size;
3195 }
3196 if (data.speed !== undefined) {
3197 this.speed = setRangeValue(data.speed);
3198 }
3199 this.spin.load(data.spin);
3200 if (data.straight !== undefined) {
3201 this.straight = data.straight;
3202 }
3203 this.trail.load(data.trail);
3204 if (data.vibrate !== undefined) {
3205 this.vibrate = data.vibrate;
3206 }
3207 if (data.warp !== undefined) {
3208 this.warp = data.warp;
3209 }
3210 }
3211}
3212;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Opacity/OpacityAnimation.js
3213
3214class OpacityAnimation extends RangedAnimationOptions {
3215 constructor() {
3216 super();
3217 this.destroy = "none";
3218 this.speed = 2;
3219 }
3220 get opacity_min() {
3221 return this.minimumValue;
3222 }
3223 set opacity_min(value) {
3224 this.minimumValue = value;
3225 }
3226 load(data) {
3227 if (data?.opacity_min !== undefined && data.minimumValue === undefined) {
3228 data.minimumValue = data.opacity_min;
3229 }
3230 super.load(data);
3231 if (!data) {
3232 return;
3233 }
3234 if (data.destroy !== undefined) {
3235 this.destroy = data.destroy;
3236 }
3237 }
3238}
3239;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Opacity/Opacity.js
3240
3241
3242
3243class Opacity extends ValueWithRandom {
3244 constructor() {
3245 super();
3246 this.animation = new OpacityAnimation();
3247 this.random.minimumValue = 0.1;
3248 this.value = 1;
3249 }
3250 get anim() {
3251 return this.animation;
3252 }
3253 set anim(value) {
3254 this.animation = value;
3255 }
3256 load(data) {
3257 if (!data) {
3258 return;
3259 }
3260 super.load(data);
3261 const animation = data.animation ?? data.anim;
3262 if (animation !== undefined) {
3263 this.animation.load(animation);
3264 this.value = setRangeValue(this.value, this.animation.enable ? this.animation.minimumValue : undefined);
3265 }
3266 }
3267}
3268;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Number/ParticlesDensity.js
3269class ParticlesDensity {
3270 constructor() {
3271 this.enable = false;
3272 this.width = 1920;
3273 this.height = 1080;
3274 }
3275 get area() {
3276 return this.width;
3277 }
3278 set area(value) {
3279 this.width = value;
3280 }
3281 get factor() {
3282 return this.height;
3283 }
3284 set factor(value) {
3285 this.height = value;
3286 }
3287 get value_area() {
3288 return this.area;
3289 }
3290 set value_area(value) {
3291 this.area = value;
3292 }
3293 load(data) {
3294 if (!data) {
3295 return;
3296 }
3297 if (data.enable !== undefined) {
3298 this.enable = data.enable;
3299 }
3300 const width = data.width ?? data.area ?? data.value_area;
3301 if (width !== undefined) {
3302 this.width = width;
3303 }
3304 const height = data.height ?? data.factor;
3305 if (height !== undefined) {
3306 this.height = height;
3307 }
3308 }
3309}
3310;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Number/ParticlesNumber.js
3311
3312class ParticlesNumber {
3313 constructor() {
3314 this.density = new ParticlesDensity();
3315 this.limit = 0;
3316 this.value = 0;
3317 }
3318 get max() {
3319 return this.limit;
3320 }
3321 set max(value) {
3322 this.limit = value;
3323 }
3324 load(data) {
3325 if (!data) {
3326 return;
3327 }
3328 this.density.load(data.density);
3329 const limit = data.limit ?? data.max;
3330 if (limit !== undefined) {
3331 this.limit = limit;
3332 }
3333 if (data.value !== undefined) {
3334 this.value = data.value;
3335 }
3336 }
3337}
3338;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Shadow.js
3339
3340class Shadow {
3341 constructor() {
3342 this.blur = 0;
3343 this.color = new OptionsColor();
3344 this.enable = false;
3345 this.offset = {
3346 x: 0,
3347 y: 0
3348 };
3349 this.color.value = "#000";
3350 }
3351 load(data) {
3352 if (!data) {
3353 return;
3354 }
3355 if (data.blur !== undefined) {
3356 this.blur = data.blur;
3357 }
3358 this.color = OptionsColor.create(this.color, data.color);
3359 if (data.enable !== undefined) {
3360 this.enable = data.enable;
3361 }
3362 if (data.offset === undefined) {
3363 return;
3364 }
3365 if (data.offset.x !== undefined) {
3366 this.offset.x = data.offset.x;
3367 }
3368 if (data.offset.y !== undefined) {
3369 this.offset.y = data.offset.y;
3370 }
3371 }
3372}
3373;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Shape/Shape.js
3374
3375const charKey = "character",
3376 charAltKey = "char",
3377 imageKey = "image",
3378 imageAltKey = "images",
3379 polygonKey = "polygon",
3380 polygonAltKey = "star";
3381class Shape {
3382 constructor() {
3383 this.loadShape = (item, mainKey, altKey, altOverride) => {
3384 if (!item) {
3385 return;
3386 }
3387 const itemIsArray = isArray(item),
3388 emptyValue = itemIsArray ? [] : {},
3389 mainDifferentValues = itemIsArray !== isArray(this.options[mainKey]),
3390 altDifferentValues = itemIsArray !== isArray(this.options[altKey]);
3391 if (mainDifferentValues) {
3392 this.options[mainKey] = emptyValue;
3393 }
3394 if (altDifferentValues && altOverride) {
3395 this.options[altKey] = emptyValue;
3396 }
3397 this.options[mainKey] = deepExtend(this.options[mainKey] ?? emptyValue, item);
3398 if (!this.options[altKey] || altOverride) {
3399 this.options[altKey] = deepExtend(this.options[altKey] ?? emptyValue, item);
3400 }
3401 };
3402 this.close = true;
3403 this.fill = true;
3404 this.options = {};
3405 this.type = "circle";
3406 }
3407 get character() {
3408 return this.options[charKey] ?? this.options[charAltKey];
3409 }
3410 set character(value) {
3411 this.options[charAltKey] = this.options[charKey] = value;
3412 }
3413 get custom() {
3414 return this.options;
3415 }
3416 set custom(value) {
3417 this.options = value;
3418 }
3419 get image() {
3420 return this.options[imageKey] ?? this.options[imageAltKey];
3421 }
3422 set image(value) {
3423 this.options[imageAltKey] = this.options[imageKey] = value;
3424 }
3425 get images() {
3426 return this.image;
3427 }
3428 set images(value) {
3429 this.image = value;
3430 }
3431 get polygon() {
3432 return this.options[polygonKey] ?? this.options[polygonAltKey];
3433 }
3434 set polygon(value) {
3435 this.options[polygonAltKey] = this.options[polygonKey] = value;
3436 }
3437 get stroke() {
3438 return [];
3439 }
3440 set stroke(_value) {}
3441 load(data) {
3442 if (!data) {
3443 return;
3444 }
3445 const options = data.options ?? data.custom;
3446 if (options !== undefined) {
3447 for (const shape in options) {
3448 const item = options[shape];
3449 if (item) {
3450 this.options[shape] = deepExtend(this.options[shape] ?? {}, item);
3451 }
3452 }
3453 }
3454 this.loadShape(data.character, charKey, charAltKey, true);
3455 this.loadShape(data.polygon, polygonKey, polygonAltKey, false);
3456 this.loadShape(data.image ?? data.images, imageKey, imageAltKey, true);
3457 if (data.close !== undefined) {
3458 this.close = data.close;
3459 }
3460 if (data.fill !== undefined) {
3461 this.fill = data.fill;
3462 }
3463 if (data.type !== undefined) {
3464 this.type = data.type;
3465 }
3466 }
3467}
3468;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Size/SizeAnimation.js
3469
3470class SizeAnimation extends RangedAnimationOptions {
3471 constructor() {
3472 super();
3473 this.destroy = "none";
3474 this.speed = 5;
3475 }
3476 get size_min() {
3477 return this.minimumValue;
3478 }
3479 set size_min(value) {
3480 this.minimumValue = value;
3481 }
3482 load(data) {
3483 if (data?.size_min !== undefined && data.minimumValue === undefined) {
3484 data.minimumValue = data.size_min;
3485 }
3486 super.load(data);
3487 if (!data) {
3488 return;
3489 }
3490 if (data.destroy !== undefined) {
3491 this.destroy = data.destroy;
3492 }
3493 }
3494}
3495;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Size/Size.js
3496
3497
3498
3499class Size extends ValueWithRandom {
3500 constructor() {
3501 super();
3502 this.animation = new SizeAnimation();
3503 this.random.minimumValue = 1;
3504 this.value = 3;
3505 }
3506 get anim() {
3507 return this.animation;
3508 }
3509 set anim(value) {
3510 this.animation = value;
3511 }
3512 load(data) {
3513 super.load(data);
3514 if (!data) {
3515 return;
3516 }
3517 const animation = data.animation ?? data.anim;
3518 if (animation !== undefined) {
3519 this.animation.load(animation);
3520 this.value = setRangeValue(this.value, this.animation.enable ? this.animation.minimumValue : undefined);
3521 }
3522 }
3523}
3524;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Stroke.js
3525
3526
3527class Stroke {
3528 constructor() {
3529 this.width = 0;
3530 }
3531 load(data) {
3532 if (!data) {
3533 return;
3534 }
3535 if (data.color !== undefined) {
3536 this.color = AnimatableColor.create(this.color, data.color);
3537 }
3538 if (data.width !== undefined) {
3539 this.width = setRangeValue(data.width);
3540 }
3541 if (data.opacity !== undefined) {
3542 this.opacity = setRangeValue(data.opacity);
3543 }
3544 }
3545}
3546;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/ZIndex/ZIndex.js
3547
3548class ZIndex extends ValueWithRandom {
3549 constructor() {
3550 super();
3551 this.opacityRate = 1;
3552 this.sizeRate = 1;
3553 this.velocityRate = 1;
3554 }
3555 load(data) {
3556 super.load(data);
3557 if (!data) {
3558 return;
3559 }
3560 if (data.opacityRate !== undefined) {
3561 this.opacityRate = data.opacityRate;
3562 }
3563 if (data.sizeRate !== undefined) {
3564 this.sizeRate = data.sizeRate;
3565 }
3566 if (data.velocityRate !== undefined) {
3567 this.velocityRate = data.velocityRate;
3568 }
3569 }
3570}
3571;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/ParticlesOptions.js
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584class ParticlesOptions {
3585 constructor(engine, container) {
3586 this._engine = engine;
3587 this._container = container;
3588 this.bounce = new ParticlesBounce();
3589 this.collisions = new Collisions();
3590 this.color = new AnimatableColor();
3591 this.color.value = "#fff";
3592 this.groups = {};
3593 this.move = new Move();
3594 this.number = new ParticlesNumber();
3595 this.opacity = new Opacity();
3596 this.reduceDuplicates = false;
3597 this.shadow = new Shadow();
3598 this.shape = new Shape();
3599 this.size = new Size();
3600 this.stroke = new Stroke();
3601 this.zIndex = new ZIndex();
3602 }
3603 load(data) {
3604 if (!data) {
3605 return;
3606 }
3607 this.bounce.load(data.bounce);
3608 this.color.load(AnimatableColor.create(this.color, data.color));
3609 if (data.groups !== undefined) {
3610 for (const group in data.groups) {
3611 const item = data.groups[group];
3612 if (item !== undefined) {
3613 this.groups[group] = deepExtend(this.groups[group] ?? {}, item);
3614 }
3615 }
3616 }
3617 this.move.load(data.move);
3618 this.number.load(data.number);
3619 this.opacity.load(data.opacity);
3620 if (data.reduceDuplicates !== undefined) {
3621 this.reduceDuplicates = data.reduceDuplicates;
3622 }
3623 this.shape.load(data.shape);
3624 this.size.load(data.size);
3625 this.shadow.load(data.shadow);
3626 this.zIndex.load(data.zIndex);
3627 const collisions = data.move?.collisions ?? data.move?.bounce;
3628 if (collisions !== undefined) {
3629 this.collisions.enable = collisions;
3630 }
3631 this.collisions.load(data.collisions);
3632 if (data.interactivity !== undefined) {
3633 this.interactivity = deepExtend({}, data.interactivity);
3634 }
3635 const strokeToLoad = data.stroke ?? data.shape?.stroke;
3636 if (strokeToLoad) {
3637 this.stroke = executeOnSingleOrMultiple(strokeToLoad, t => {
3638 const tmp = new Stroke();
3639 tmp.load(t);
3640 return tmp;
3641 });
3642 }
3643 if (this._container) {
3644 const updaters = this._engine.plugins.updaters.get(this._container);
3645 if (updaters) {
3646 for (const updater of updaters) {
3647 if (updater.loadOptions) {
3648 updater.loadOptions(this, data);
3649 }
3650 }
3651 }
3652 const interactors = this._engine.plugins.interactors.get(this._container);
3653 if (interactors) {
3654 for (const interactor of interactors) {
3655 if (interactor.loadParticlesOptions) {
3656 interactor.loadParticlesOptions(this, data);
3657 }
3658 }
3659 }
3660 }
3661 }
3662}
3663;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/OptionsUtils.js
3664
3665function loadOptions(options, ...sourceOptionsArr) {
3666 for (const sourceOptions of sourceOptionsArr) {
3667 options.load(sourceOptions);
3668 }
3669}
3670function loadParticlesOptions(engine, container, ...sourceOptionsArr) {
3671 const options = new ParticlesOptions(engine, container);
3672 loadOptions(options, ...sourceOptionsArr);
3673 return options;
3674}
3675;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Options.js
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686class Options {
3687 constructor(engine, container) {
3688 this._findDefaultTheme = mode => {
3689 return this.themes.find(theme => theme.default.value && theme.default.mode === mode) ?? this.themes.find(theme => theme.default.value && theme.default.mode === "any");
3690 };
3691 this._importPreset = preset => {
3692 this.load(this._engine.plugins.getPreset(preset));
3693 };
3694 this._engine = engine;
3695 this._container = container;
3696 this.autoPlay = true;
3697 this.background = new Background();
3698 this.backgroundMask = new BackgroundMask();
3699 this.defaultThemes = {};
3700 this.delay = 0;
3701 this.fullScreen = new FullScreen();
3702 this.detectRetina = true;
3703 this.duration = 0;
3704 this.fpsLimit = 120;
3705 this.interactivity = new Interactivity(engine, container);
3706 this.manualParticles = [];
3707 this.particles = loadParticlesOptions(this._engine, this._container);
3708 this.pauseOnBlur = true;
3709 this.pauseOnOutsideViewport = true;
3710 this.responsive = [];
3711 this.smooth = false;
3712 this.style = {};
3713 this.themes = [];
3714 this.zLayers = 100;
3715 }
3716 get backgroundMode() {
3717 return this.fullScreen;
3718 }
3719 set backgroundMode(value) {
3720 this.fullScreen.load(value);
3721 }
3722 get fps_limit() {
3723 return this.fpsLimit;
3724 }
3725 set fps_limit(value) {
3726 this.fpsLimit = value;
3727 }
3728 get retina_detect() {
3729 return this.detectRetina;
3730 }
3731 set retina_detect(value) {
3732 this.detectRetina = value;
3733 }
3734 load(data) {
3735 if (!data) {
3736 return;
3737 }
3738 if (data.preset !== undefined) {
3739 executeOnSingleOrMultiple(data.preset, preset => this._importPreset(preset));
3740 }
3741 if (data.autoPlay !== undefined) {
3742 this.autoPlay = data.autoPlay;
3743 }
3744 if (data.delay !== undefined) {
3745 this.delay = setRangeValue(data.delay);
3746 }
3747 const detectRetina = data.detectRetina ?? data.retina_detect;
3748 if (detectRetina !== undefined) {
3749 this.detectRetina = detectRetina;
3750 }
3751 if (data.duration !== undefined) {
3752 this.duration = setRangeValue(data.duration);
3753 }
3754 const fpsLimit = data.fpsLimit ?? data.fps_limit;
3755 if (fpsLimit !== undefined) {
3756 this.fpsLimit = fpsLimit;
3757 }
3758 if (data.pauseOnBlur !== undefined) {
3759 this.pauseOnBlur = data.pauseOnBlur;
3760 }
3761 if (data.pauseOnOutsideViewport !== undefined) {
3762 this.pauseOnOutsideViewport = data.pauseOnOutsideViewport;
3763 }
3764 if (data.zLayers !== undefined) {
3765 this.zLayers = data.zLayers;
3766 }
3767 this.background.load(data.background);
3768 const fullScreen = data.fullScreen ?? data.backgroundMode;
3769 if (isBoolean(fullScreen)) {
3770 this.fullScreen.enable = fullScreen;
3771 } else {
3772 this.fullScreen.load(fullScreen);
3773 }
3774 this.backgroundMask.load(data.backgroundMask);
3775 this.interactivity.load(data.interactivity);
3776 if (data.manualParticles) {
3777 this.manualParticles = data.manualParticles.map(t => {
3778 const tmp = new ManualParticle();
3779 tmp.load(t);
3780 return tmp;
3781 });
3782 }
3783 this.particles.load(data.particles);
3784 this.style = deepExtend(this.style, data.style);
3785 this._engine.plugins.loadOptions(this, data);
3786 if (data.smooth !== undefined) {
3787 this.smooth = data.smooth;
3788 }
3789 const interactors = this._engine.plugins.interactors.get(this._container);
3790 if (interactors) {
3791 for (const interactor of interactors) {
3792 if (interactor.loadOptions) {
3793 interactor.loadOptions(this, data);
3794 }
3795 }
3796 }
3797 if (data.responsive !== undefined) {
3798 for (const responsive of data.responsive) {
3799 const optResponsive = new Responsive();
3800 optResponsive.load(responsive);
3801 this.responsive.push(optResponsive);
3802 }
3803 }
3804 this.responsive.sort((a, b) => a.maxWidth - b.maxWidth);
3805 if (data.themes !== undefined) {
3806 for (const theme of data.themes) {
3807 const existingTheme = this.themes.find(t => t.name === theme.name);
3808 if (!existingTheme) {
3809 const optTheme = new Theme();
3810 optTheme.load(theme);
3811 this.themes.push(optTheme);
3812 } else {
3813 existingTheme.load(theme);
3814 }
3815 }
3816 }
3817 this.defaultThemes.dark = this._findDefaultTheme("dark")?.name;
3818 this.defaultThemes.light = this._findDefaultTheme("light")?.name;
3819 }
3820 setResponsive(width, pxRatio, defaultOptions) {
3821 this.load(defaultOptions);
3822 const responsiveOptions = this.responsive.find(t => t.mode === "screen" && screen ? t.maxWidth > screen.availWidth : t.maxWidth * pxRatio > width);
3823 this.load(responsiveOptions?.options);
3824 return responsiveOptions?.maxWidth;
3825 }
3826 setTheme(name) {
3827 if (name) {
3828 const chosenTheme = this.themes.find(theme => theme.name === name);
3829 if (chosenTheme) {
3830 this.load(chosenTheme.options);
3831 }
3832 } else {
3833 const mediaMatch = safeMatchMedia("(prefers-color-scheme: dark)"),
3834 clientDarkMode = mediaMatch && mediaMatch.matches,
3835 defaultTheme = this._findDefaultTheme(clientDarkMode ? "dark" : "light");
3836 if (defaultTheme) {
3837 this.load(defaultTheme.options);
3838 }
3839 }
3840 }
3841}
3842;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/InteractionManager.js
3843class InteractionManager {
3844 constructor(engine, container) {
3845 this.container = container;
3846 this._engine = engine;
3847 this._interactors = engine.plugins.getInteractors(this.container, true);
3848 this._externalInteractors = [];
3849 this._particleInteractors = [];
3850 }
3851 async externalInteract(delta) {
3852 for (const interactor of this._externalInteractors) {
3853 interactor.isEnabled() && (await interactor.interact(delta));
3854 }
3855 }
3856 handleClickMode(mode) {
3857 for (const interactor of this._externalInteractors) {
3858 interactor.handleClickMode && interactor.handleClickMode(mode);
3859 }
3860 }
3861 init() {
3862 this._externalInteractors = [];
3863 this._particleInteractors = [];
3864 for (const interactor of this._interactors) {
3865 switch (interactor.type) {
3866 case "external":
3867 this._externalInteractors.push(interactor);
3868 break;
3869 case "particles":
3870 this._particleInteractors.push(interactor);
3871 break;
3872 }
3873 interactor.init();
3874 }
3875 }
3876 async particlesInteract(particle, delta) {
3877 for (const interactor of this._externalInteractors) {
3878 interactor.clear(particle, delta);
3879 }
3880 for (const interactor of this._particleInteractors) {
3881 interactor.isEnabled(particle) && (await interactor.interact(particle, delta));
3882 }
3883 }
3884 async reset(particle) {
3885 for (const interactor of this._externalInteractors) {
3886 interactor.isEnabled() && interactor.reset(particle);
3887 }
3888 for (const interactor of this._particleInteractors) {
3889 interactor.isEnabled(particle) && interactor.reset(particle);
3890 }
3891 }
3892}
3893;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Particle.js
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903const fixOutMode = data => {
3904 if (!isInArray(data.outMode, data.checkModes)) {
3905 return;
3906 }
3907 const diameter = data.radius * 2;
3908 if (data.coord > data.maxCoord - diameter) {
3909 data.setCb(-data.radius);
3910 } else if (data.coord < diameter) {
3911 data.setCb(data.radius);
3912 }
3913};
3914class Particle {
3915 constructor(engine, id, container, position, overrideOptions, group) {
3916 this.container = container;
3917 this._calcPosition = (container, position, zIndex, tryCount = 0) => {
3918 for (const [, plugin] of container.plugins) {
3919 const pluginPos = plugin.particlePosition !== undefined ? plugin.particlePosition(position, this) : undefined;
3920 if (pluginPos) {
3921 return Vector3d.create(pluginPos.x, pluginPos.y, zIndex);
3922 }
3923 }
3924 const canvasSize = container.canvas.size,
3925 exactPosition = calcExactPositionOrRandomFromSize({
3926 size: canvasSize,
3927 position: position
3928 }),
3929 pos = Vector3d.create(exactPosition.x, exactPosition.y, zIndex),
3930 radius = this.getRadius(),
3931 outModes = this.options.move.outModes,
3932 fixHorizontal = outMode => {
3933 fixOutMode({
3934 outMode,
3935 checkModes: ["bounce", "bounce-horizontal"],
3936 coord: pos.x,
3937 maxCoord: container.canvas.size.width,
3938 setCb: value => pos.x += value,
3939 radius
3940 });
3941 },
3942 fixVertical = outMode => {
3943 fixOutMode({
3944 outMode,
3945 checkModes: ["bounce", "bounce-vertical"],
3946 coord: pos.y,
3947 maxCoord: container.canvas.size.height,
3948 setCb: value => pos.y += value,
3949 radius
3950 });
3951 };
3952 fixHorizontal(outModes.left ?? outModes.default);
3953 fixHorizontal(outModes.right ?? outModes.default);
3954 fixVertical(outModes.top ?? outModes.default);
3955 fixVertical(outModes.bottom ?? outModes.default);
3956 if (this._checkOverlap(pos, tryCount)) {
3957 return this._calcPosition(container, undefined, zIndex, tryCount + 1);
3958 }
3959 return pos;
3960 };
3961 this._calculateVelocity = () => {
3962 const baseVelocity = getParticleBaseVelocity(this.direction),
3963 res = baseVelocity.copy(),
3964 moveOptions = this.options.move;
3965 if (moveOptions.direction === "inside" || moveOptions.direction === "outside") {
3966 return res;
3967 }
3968 const rad = Math.PI / 180 * getRangeValue(moveOptions.angle.value),
3969 radOffset = Math.PI / 180 * getRangeValue(moveOptions.angle.offset),
3970 range = {
3971 left: radOffset - rad / 2,
3972 right: radOffset + rad / 2
3973 };
3974 if (!moveOptions.straight) {
3975 res.angle += randomInRange(setRangeValue(range.left, range.right));
3976 }
3977 if (moveOptions.random && typeof moveOptions.speed === "number") {
3978 res.length *= getRandom();
3979 }
3980 return res;
3981 };
3982 this._checkOverlap = (pos, tryCount = 0) => {
3983 const collisionsOptions = this.options.collisions,
3984 radius = this.getRadius();
3985 if (!collisionsOptions.enable) {
3986 return false;
3987 }
3988 const overlapOptions = collisionsOptions.overlap;
3989 if (overlapOptions.enable) {
3990 return false;
3991 }
3992 const retries = overlapOptions.retries;
3993 if (retries >= 0 && tryCount > retries) {
3994 throw new Error(`${errorPrefix} particle is overlapping and can't be placed`);
3995 }
3996 return !!this.container.particles.find(particle => getDistance(pos, particle.position) < radius + particle.getRadius());
3997 };
3998 this._getRollColor = color => {
3999 if (!color || !this.roll || !this.backColor && !this.roll.alter) {
4000 return color;
4001 }
4002 const backFactor = this.roll.horizontal && this.roll.vertical ? 2 : 1,
4003 backSum = this.roll.horizontal ? Math.PI / 2 : 0,
4004 rolled = Math.floor(((this.roll.angle ?? 0) + backSum) / (Math.PI / backFactor)) % 2;
4005 if (!rolled) {
4006 return color;
4007 }
4008 if (this.backColor) {
4009 return this.backColor;
4010 }
4011 if (this.roll.alter) {
4012 return alterHsl(color, this.roll.alter.type, this.roll.alter.value);
4013 }
4014 return color;
4015 };
4016 this._initPosition = position => {
4017 const container = this.container,
4018 zIndexValue = getRangeValue(this.options.zIndex.value);
4019 this.position = this._calcPosition(container, position, clamp(zIndexValue, 0, container.zLayers));
4020 this.initialPosition = this.position.copy();
4021 const canvasSize = container.canvas.size;
4022 this.moveCenter = {
4023 ...getPosition(this.options.move.center, canvasSize),
4024 radius: this.options.move.center.radius ?? 0,
4025 mode: this.options.move.center.mode ?? "percent"
4026 };
4027 this.direction = getParticleDirectionAngle(this.options.move.direction, this.position, this.moveCenter);
4028 switch (this.options.move.direction) {
4029 case "inside":
4030 this.outType = "inside";
4031 break;
4032 case "outside":
4033 this.outType = "outside";
4034 break;
4035 }
4036 this.offset = Vector.origin;
4037 };
4038 this._loadShapeData = (shapeOptions, reduceDuplicates) => {
4039 const shapeData = shapeOptions.options[this.shape];
4040 if (!shapeData) {
4041 return;
4042 }
4043 return deepExtend({
4044 close: shapeOptions.close,
4045 fill: shapeOptions.fill
4046 }, itemFromSingleOrMultiple(shapeData, this.id, reduceDuplicates));
4047 };
4048 this._engine = engine;
4049 this.init(id, position, overrideOptions, group);
4050 }
4051 destroy(override) {
4052 if (this.unbreakable || this.destroyed) {
4053 return;
4054 }
4055 this.destroyed = true;
4056 this.bubble.inRange = false;
4057 this.slow.inRange = false;
4058 const container = this.container,
4059 pathGenerator = this.pathGenerator;
4060 for (const [, plugin] of container.plugins) {
4061 if (plugin.particleDestroyed) {
4062 plugin.particleDestroyed(this, override);
4063 }
4064 }
4065 for (const updater of container.particles.updaters) {
4066 if (updater.particleDestroyed) {
4067 updater.particleDestroyed(this, override);
4068 }
4069 }
4070 if (pathGenerator) {
4071 pathGenerator.reset(this);
4072 }
4073 }
4074 draw(delta) {
4075 const container = this.container;
4076 for (const [, plugin] of container.plugins) {
4077 container.canvas.drawParticlePlugin(plugin, this, delta);
4078 }
4079 container.canvas.drawParticle(this, delta);
4080 }
4081 getFillColor() {
4082 return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.color));
4083 }
4084 getMass() {
4085 return this.getRadius() ** 2 * Math.PI / 2;
4086 }
4087 getPosition() {
4088 return {
4089 x: this.position.x + this.offset.x,
4090 y: this.position.y + this.offset.y,
4091 z: this.position.z
4092 };
4093 }
4094 getRadius() {
4095 return this.bubble.radius ?? this.size.value;
4096 }
4097 getStrokeColor() {
4098 return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
4099 }
4100 init(id, position, overrideOptions, group) {
4101 const container = this.container,
4102 engine = this._engine;
4103 this.id = id;
4104 this.group = group;
4105 this.fill = true;
4106 this.pathRotation = false;
4107 this.close = true;
4108 this.lastPathTime = 0;
4109 this.destroyed = false;
4110 this.unbreakable = false;
4111 this.rotation = 0;
4112 this.misplaced = false;
4113 this.retina = {
4114 maxDistance: {}
4115 };
4116 this.outType = "normal";
4117 this.ignoresResizeRatio = true;
4118 const pxRatio = container.retina.pixelRatio,
4119 mainOptions = container.actualOptions,
4120 particlesOptions = loadParticlesOptions(this._engine, container, mainOptions.particles),
4121 shapeType = particlesOptions.shape.type,
4122 {
4123 reduceDuplicates
4124 } = particlesOptions;
4125 this.shape = itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
4126 const shapeOptions = particlesOptions.shape;
4127 if (overrideOptions && overrideOptions.shape && overrideOptions.shape.type) {
4128 const overrideShapeType = overrideOptions.shape.type,
4129 shape = itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
4130 if (shape) {
4131 this.shape = shape;
4132 shapeOptions.load(overrideOptions.shape);
4133 }
4134 }
4135 this.shapeData = this._loadShapeData(shapeOptions, reduceDuplicates);
4136 particlesOptions.load(overrideOptions);
4137 const shapeData = this.shapeData;
4138 if (shapeData) {
4139 particlesOptions.load(shapeData.particles);
4140 }
4141 const interactivity = new Interactivity(engine, container);
4142 interactivity.load(container.actualOptions.interactivity);
4143 interactivity.load(particlesOptions.interactivity);
4144 this.interactivity = interactivity;
4145 this.fill = shapeData?.fill ?? particlesOptions.shape.fill;
4146 this.close = shapeData?.close ?? particlesOptions.shape.close;
4147 this.options = particlesOptions;
4148 const pathOptions = this.options.move.path;
4149 this.pathDelay = getValue(pathOptions.delay) * 1000;
4150 if (pathOptions.generator) {
4151 this.pathGenerator = this._engine.plugins.getPathGenerator(pathOptions.generator);
4152 if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
4153 this.pathGenerator.init(container);
4154 }
4155 }
4156 container.retina.initParticle(this);
4157 this.size = initParticleNumericAnimationValue(this.options.size, pxRatio);
4158 this.bubble = {
4159 inRange: false
4160 };
4161 this.slow = {
4162 inRange: false,
4163 factor: 1
4164 };
4165 this._initPosition(position);
4166 this.initialVelocity = this._calculateVelocity();
4167 this.velocity = this.initialVelocity.copy();
4168 this.moveDecay = 1 - getRangeValue(this.options.move.decay);
4169 const particles = container.particles;
4170 particles.needsSort = particles.needsSort || particles.lastZIndex < this.position.z;
4171 particles.lastZIndex = this.position.z;
4172 this.zIndexFactor = this.position.z / container.zLayers;
4173 this.sides = 24;
4174 let drawer = container.drawers.get(this.shape);
4175 if (!drawer) {
4176 drawer = this._engine.plugins.getShapeDrawer(this.shape);
4177 if (drawer) {
4178 container.drawers.set(this.shape, drawer);
4179 }
4180 }
4181 if (drawer && drawer.loadShape) {
4182 drawer.loadShape(this);
4183 }
4184 const sideCountFunc = drawer?.getSidesCount;
4185 if (sideCountFunc) {
4186 this.sides = sideCountFunc(this);
4187 }
4188 this.spawning = false;
4189 this.shadowColor = rangeColorToRgb(this.options.shadow.color);
4190 for (const updater of container.particles.updaters) {
4191 updater.init(this);
4192 }
4193 for (const mover of container.particles.movers) {
4194 mover.init && mover.init(this);
4195 }
4196 if (drawer && drawer.particleInit) {
4197 drawer.particleInit(container, this);
4198 }
4199 for (const [, plugin] of container.plugins) {
4200 plugin.particleCreated && plugin.particleCreated(this);
4201 }
4202 }
4203 isInsideCanvas() {
4204 const radius = this.getRadius(),
4205 canvasSize = this.container.canvas.size,
4206 position = this.position;
4207 return position.x >= -radius && position.y >= -radius && position.y <= canvasSize.height + radius && position.x <= canvasSize.width + radius;
4208 }
4209 isVisible() {
4210 return !this.destroyed && !this.spawning && this.isInsideCanvas();
4211 }
4212 reset() {
4213 for (const updater of this.container.particles.updaters) {
4214 updater.reset && updater.reset(this);
4215 }
4216 }
4217}
4218;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Point.js
4219class Point {
4220 constructor(position, particle) {
4221 this.position = position;
4222 this.particle = particle;
4223 }
4224}
4225;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Range.js
4226class Range {
4227 constructor(x, y) {
4228 this.position = {
4229 x: x,
4230 y: y
4231 };
4232 }
4233}
4234;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Rectangle.js
4235
4236
4237class Rectangle extends Range {
4238 constructor(x, y, width, height) {
4239 super(x, y);
4240 this.size = {
4241 height: height,
4242 width: width
4243 };
4244 }
4245 contains(point) {
4246 const w = this.size.width,
4247 h = this.size.height,
4248 pos = this.position;
4249 return point.x >= pos.x && point.x <= pos.x + w && point.y >= pos.y && point.y <= pos.y + h;
4250 }
4251 intersects(range) {
4252 if (range instanceof Circle) {
4253 range.intersects(this);
4254 }
4255 const w = this.size.width,
4256 h = this.size.height,
4257 pos1 = this.position,
4258 pos2 = range.position,
4259 size2 = range instanceof Rectangle ? range.size : {
4260 width: 0,
4261 height: 0
4262 },
4263 w2 = size2.width,
4264 h2 = size2.height;
4265 return pos2.x < pos1.x + w && pos2.x + w2 > pos1.x && pos2.y < pos1.y + h && pos2.y + h2 > pos1.y;
4266 }
4267}
4268;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Circle.js
4269
4270
4271
4272class Circle extends Range {
4273 constructor(x, y, radius) {
4274 super(x, y);
4275 this.radius = radius;
4276 }
4277 contains(point) {
4278 return getDistance(point, this.position) <= this.radius;
4279 }
4280 intersects(range) {
4281 const pos1 = this.position,
4282 pos2 = range.position,
4283 distPos = {
4284 x: Math.abs(pos2.x - pos1.x),
4285 y: Math.abs(pos2.y - pos1.y)
4286 },
4287 r = this.radius;
4288 if (range instanceof Circle) {
4289 const rSum = r + range.radius,
4290 dist = Math.sqrt(distPos.x ** 2 + distPos.y ** 2);
4291 return rSum > dist;
4292 } else if (range instanceof Rectangle) {
4293 const {
4294 width,
4295 height
4296 } = range.size,
4297 edges = Math.pow(distPos.x - width, 2) + Math.pow(distPos.y - height, 2);
4298 return edges <= r ** 2 || distPos.x <= r + width && distPos.y <= r + height || distPos.x <= width || distPos.y <= height;
4299 }
4300 return false;
4301 }
4302}
4303;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/QuadTree.js
4304
4305
4306
4307class QuadTree {
4308 constructor(rectangle, capacity) {
4309 this.rectangle = rectangle;
4310 this.capacity = capacity;
4311 this._subdivide = () => {
4312 const {
4313 x,
4314 y
4315 } = this.rectangle.position,
4316 {
4317 width,
4318 height
4319 } = this.rectangle.size,
4320 {
4321 capacity
4322 } = this;
4323 for (let i = 0; i < 4; i++) {
4324 this._subs.push(new QuadTree(new Rectangle(x + width / 2 * (i % 2), y + height / 2 * (Math.round(i / 2) - i % 2), width / 2, height / 2), capacity));
4325 }
4326 this._divided = true;
4327 };
4328 this._points = [];
4329 this._divided = false;
4330 this._subs = [];
4331 }
4332 insert(point) {
4333 if (!this.rectangle.contains(point.position)) {
4334 return false;
4335 }
4336 if (this._points.length < this.capacity) {
4337 this._points.push(point);
4338 return true;
4339 }
4340 if (!this._divided) {
4341 this._subdivide();
4342 }
4343 return this._subs.some(sub => sub.insert(point));
4344 }
4345 query(range, check, found) {
4346 const res = found || [];
4347 if (!range.intersects(this.rectangle)) {
4348 return [];
4349 }
4350 for (const p of this._points) {
4351 if (!range.contains(p.position) && getDistance(range.position, p.position) > p.particle.getRadius() && (!check || check(p.particle))) {
4352 continue;
4353 }
4354 res.push(p.particle);
4355 }
4356 if (this._divided) {
4357 for (const sub of this._subs) {
4358 sub.query(range, check, res);
4359 }
4360 }
4361 return res;
4362 }
4363 queryCircle(position, radius, check) {
4364 return this.query(new Circle(position.x, position.y, radius), check);
4365 }
4366 queryRectangle(position, size, check) {
4367 return this.query(new Rectangle(position.x, position.y, size.width, size.height), check);
4368 }
4369}
4370;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Particles.js
4371
4372
4373
4374
4375
4376
4377
4378const qTreeCapacity = 4;
4379const qTreeRectangle = canvasSize => {
4380 return new Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, canvasSize.width * 3 / 2, canvasSize.height * 3 / 2);
4381};
4382class Particles {
4383 constructor(engine, container) {
4384 this._applyDensity = (options, manualCount, group) => {
4385 if (!options.number.density?.enable) {
4386 return;
4387 }
4388 const numberOptions = options.number,
4389 densityFactor = this._initDensityFactor(numberOptions.density),
4390 optParticlesNumber = numberOptions.value,
4391 optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber,
4392 particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount,
4393 particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
4394 this.limit = numberOptions.limit * densityFactor;
4395 if (particlesCount < particlesNumber) {
4396 this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
4397 } else if (particlesCount > particlesNumber) {
4398 this.removeQuantity(particlesCount - particlesNumber, group);
4399 }
4400 };
4401 this._initDensityFactor = densityOptions => {
4402 const container = this._container;
4403 if (!container.canvas.element || !densityOptions.enable) {
4404 return 1;
4405 }
4406 const canvas = container.canvas.element,
4407 pxRatio = container.retina.pixelRatio;
4408 return canvas.width * canvas.height / (densityOptions.factor * pxRatio ** 2 * densityOptions.area);
4409 };
4410 this._pushParticle = (position, overrideOptions, group, initializer) => {
4411 try {
4412 let particle = this.pool.pop();
4413 if (particle) {
4414 particle.init(this._nextId, position, overrideOptions, group);
4415 } else {
4416 particle = new Particle(this._engine, this._nextId, this._container, position, overrideOptions, group);
4417 }
4418 let canAdd = true;
4419 if (initializer) {
4420 canAdd = initializer(particle);
4421 }
4422 if (!canAdd) {
4423 return;
4424 }
4425 this._array.push(particle);
4426 this._zArray.push(particle);
4427 this._nextId++;
4428 this._engine.dispatchEvent("particleAdded", {
4429 container: this._container,
4430 data: {
4431 particle
4432 }
4433 });
4434 return particle;
4435 } catch (e) {
4436 getLogger().warning(`${errorPrefix} adding particle: ${e}`);
4437 return;
4438 }
4439 };
4440 this._removeParticle = (index, group, override) => {
4441 const particle = this._array[index];
4442 if (!particle || particle.group !== group) {
4443 return false;
4444 }
4445 particle.destroy(override);
4446 const zIdx = this._zArray.indexOf(particle);
4447 this._array.splice(index, 1);
4448 this._zArray.splice(zIdx, 1);
4449 this.pool.push(particle);
4450 this._engine.dispatchEvent("particleRemoved", {
4451 container: this._container,
4452 data: {
4453 particle
4454 }
4455 });
4456 return true;
4457 };
4458 this._engine = engine;
4459 this._container = container;
4460 this._nextId = 0;
4461 this._array = [];
4462 this._zArray = [];
4463 this.pool = [];
4464 this.limit = 0;
4465 this.needsSort = false;
4466 this.lastZIndex = 0;
4467 this._interactionManager = new InteractionManager(engine, container);
4468 const canvasSize = container.canvas.size;
4469 this.quadTree = new QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
4470 this.movers = this._engine.plugins.getMovers(container, true);
4471 this.updaters = this._engine.plugins.getUpdaters(container, true);
4472 }
4473 get count() {
4474 return this._array.length;
4475 }
4476 addManualParticles() {
4477 const container = this._container,
4478 options = container.actualOptions;
4479 for (const particle of options.manualParticles) {
4480 this.addParticle(particle.position ? getPosition(particle.position, container.canvas.size) : undefined, particle.options);
4481 }
4482 }
4483 addParticle(position, overrideOptions, group, initializer) {
4484 const container = this._container,
4485 options = container.actualOptions,
4486 limit = options.particles.number.limit;
4487 if (limit > 0) {
4488 const countToRemove = this.count + 1 - limit;
4489 if (countToRemove > 0) {
4490 this.removeQuantity(countToRemove);
4491 }
4492 }
4493 return this._pushParticle(position, overrideOptions, group, initializer);
4494 }
4495 clear() {
4496 this._array = [];
4497 this._zArray = [];
4498 }
4499 destroy() {
4500 this._array = [];
4501 this._zArray = [];
4502 this.movers = [];
4503 this.updaters = [];
4504 }
4505 async draw(delta) {
4506 const container = this._container;
4507 container.canvas.clear();
4508 await this.update(delta);
4509 for (const [, plugin] of container.plugins) {
4510 container.canvas.drawPlugin(plugin, delta);
4511 }
4512 for (const p of this._zArray) {
4513 p.draw(delta);
4514 }
4515 }
4516 filter(condition) {
4517 return this._array.filter(condition);
4518 }
4519 find(condition) {
4520 return this._array.find(condition);
4521 }
4522 handleClickMode(mode) {
4523 this._interactionManager.handleClickMode(mode);
4524 }
4525 init() {
4526 const container = this._container,
4527 options = container.actualOptions;
4528 this.lastZIndex = 0;
4529 this.needsSort = false;
4530 let handled = false;
4531 this.updaters = this._engine.plugins.getUpdaters(container, true);
4532 this._interactionManager.init();
4533 for (const [, plugin] of container.plugins) {
4534 if (plugin.particlesInitialization !== undefined) {
4535 handled = plugin.particlesInitialization();
4536 }
4537 if (handled) {
4538 break;
4539 }
4540 }
4541 this._interactionManager.init();
4542 for (const [, pathGenerator] of container.pathGenerators) {
4543 pathGenerator.init(container);
4544 }
4545 this.addManualParticles();
4546 if (!handled) {
4547 for (const group in options.particles.groups) {
4548 const groupOptions = options.particles.groups[group];
4549 for (let i = this.count, j = 0; j < groupOptions.number?.value && i < options.particles.number.value; i++, j++) {
4550 this.addParticle(undefined, groupOptions, group);
4551 }
4552 }
4553 for (let i = this.count; i < options.particles.number.value; i++) {
4554 this.addParticle();
4555 }
4556 }
4557 }
4558 push(nb, mouse, overrideOptions, group) {
4559 this.pushing = true;
4560 for (let i = 0; i < nb; i++) {
4561 this.addParticle(mouse?.position, overrideOptions, group);
4562 }
4563 this.pushing = false;
4564 }
4565 async redraw() {
4566 this.clear();
4567 this.init();
4568 await this.draw({
4569 value: 0,
4570 factor: 0
4571 });
4572 }
4573 remove(particle, group, override) {
4574 this.removeAt(this._array.indexOf(particle), undefined, group, override);
4575 }
4576 removeAt(index, quantity = 1, group, override) {
4577 if (index < 0 || index > this.count) {
4578 return;
4579 }
4580 let deleted = 0;
4581 for (let i = index; deleted < quantity && i < this.count; i++) {
4582 this._removeParticle(i--, group, override) && deleted++;
4583 }
4584 }
4585 removeQuantity(quantity, group) {
4586 this.removeAt(0, quantity, group);
4587 }
4588 setDensity() {
4589 const options = this._container.actualOptions,
4590 groups = options.particles.groups;
4591 for (const group in groups) {
4592 this._applyDensity(groups[group], 0, group);
4593 }
4594 this._applyDensity(options.particles, options.manualParticles.length);
4595 }
4596 async update(delta) {
4597 const container = this._container,
4598 particlesToDelete = new Set();
4599 this.quadTree = new QuadTree(qTreeRectangle(container.canvas.size), qTreeCapacity);
4600 for (const [, pathGenerator] of container.pathGenerators) {
4601 pathGenerator.update();
4602 }
4603 for (const [, plugin] of container.plugins) {
4604 plugin.update && plugin.update(delta);
4605 }
4606 for (const particle of this._array) {
4607 const resizeFactor = container.canvas.resizeFactor;
4608 if (resizeFactor && !particle.ignoresResizeRatio) {
4609 particle.position.x *= resizeFactor.width;
4610 particle.position.y *= resizeFactor.height;
4611 particle.initialPosition.x *= resizeFactor.width;
4612 particle.initialPosition.y *= resizeFactor.height;
4613 }
4614 particle.ignoresResizeRatio = false;
4615 await this._interactionManager.reset(particle);
4616 for (const [, plugin] of this._container.plugins) {
4617 if (particle.destroyed) {
4618 break;
4619 }
4620 if (plugin.particleUpdate) {
4621 plugin.particleUpdate(particle, delta);
4622 }
4623 }
4624 for (const mover of this.movers) {
4625 mover.isEnabled(particle) && mover.move(particle, delta);
4626 }
4627 if (particle.destroyed) {
4628 particlesToDelete.add(particle);
4629 continue;
4630 }
4631 this.quadTree.insert(new Point(particle.getPosition(), particle));
4632 }
4633 if (particlesToDelete.size) {
4634 const checkDelete = p => !particlesToDelete.has(p);
4635 this._array = this.filter(checkDelete);
4636 this._zArray = this._zArray.filter(checkDelete);
4637 this.pool.push(...particlesToDelete);
4638 }
4639 await this._interactionManager.externalInteract(delta);
4640 for (const particle of this._array) {
4641 for (const updater of this.updaters) {
4642 updater.update(particle, delta);
4643 }
4644 if (!particle.destroyed && !particle.spawning) {
4645 await this._interactionManager.particlesInteract(particle, delta);
4646 }
4647 }
4648 delete container.canvas.resizeFactor;
4649 if (this.needsSort) {
4650 const zArray = this._zArray;
4651 zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
4652 this.lastZIndex = zArray[zArray.length - 1].position.z;
4653 this.needsSort = false;
4654 }
4655 }
4656}
4657;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Retina.js
4658
4659
4660class Retina {
4661 constructor(container) {
4662 this.container = container;
4663 this.pixelRatio = 1;
4664 this.reduceFactor = 1;
4665 }
4666 init() {
4667 const container = this.container,
4668 options = container.actualOptions;
4669 this.pixelRatio = !options.detectRetina || isSsr() ? 1 : window.devicePixelRatio;
4670 this.reduceFactor = 1;
4671 const ratio = this.pixelRatio;
4672 if (container.canvas.element) {
4673 const element = container.canvas.element;
4674 container.canvas.size.width = element.offsetWidth * ratio;
4675 container.canvas.size.height = element.offsetHeight * ratio;
4676 }
4677 const particles = options.particles,
4678 moveOptions = particles.move;
4679 this.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4680 this.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
4681 this.sizeAnimationSpeed = getRangeValue(particles.size.animation.speed) * ratio;
4682 }
4683 initParticle(particle) {
4684 const options = particle.options,
4685 ratio = this.pixelRatio,
4686 moveOptions = options.move,
4687 moveDistance = moveOptions.distance,
4688 props = particle.retina;
4689 props.attractDistance = getRangeValue(moveOptions.attract.distance) * ratio;
4690 props.moveDrift = getRangeValue(moveOptions.drift) * ratio;
4691 props.moveSpeed = getRangeValue(moveOptions.speed) * ratio;
4692 props.sizeAnimationSpeed = getRangeValue(options.size.animation.speed) * ratio;
4693 const maxDistance = props.maxDistance;
4694 maxDistance.horizontal = moveDistance.horizontal !== undefined ? moveDistance.horizontal * ratio : undefined;
4695 maxDistance.vertical = moveDistance.vertical !== undefined ? moveDistance.vertical * ratio : undefined;
4696 props.maxSpeed = getRangeValue(moveOptions.gravity.maxSpeed) * ratio;
4697 }
4698}
4699;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Container.js
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709function guardCheck(container) {
4710 return container && !container.destroyed;
4711}
4712function initDelta(value, fpsLimit = 60, smooth = false) {
4713 return {
4714 value,
4715 factor: smooth ? 60 / fpsLimit : 60 * value / 1000
4716 };
4717}
4718function loadContainerOptions(engine, container, ...sourceOptionsArr) {
4719 const options = new Options(engine, container);
4720 loadOptions(options, ...sourceOptionsArr);
4721 return options;
4722}
4723const defaultPathGeneratorKey = "default",
4724 defaultPathGenerator = {
4725 generate: p => p.velocity,
4726 init: () => {},
4727 update: () => {},
4728 reset: () => {}
4729 };
4730class Container {
4731 constructor(engine, id, sourceOptions) {
4732 this.id = id;
4733 this._intersectionManager = entries => {
4734 if (!guardCheck(this) || !this.actualOptions.pauseOnOutsideViewport) {
4735 return;
4736 }
4737 for (const entry of entries) {
4738 if (entry.target !== this.interactivity.element) {
4739 continue;
4740 }
4741 (entry.isIntersecting ? this.play : this.pause)();
4742 }
4743 };
4744 this._nextFrame = async timestamp => {
4745 try {
4746 if (!this.smooth && this.lastFrameTime !== undefined && timestamp < this.lastFrameTime + 1000 / this.fpsLimit) {
4747 this.draw(false);
4748 return;
4749 }
4750 this.lastFrameTime ??= timestamp;
4751 const delta = initDelta(timestamp - this.lastFrameTime, this.fpsLimit, this.smooth);
4752 this.addLifeTime(delta.value);
4753 this.lastFrameTime = timestamp;
4754 if (delta.value > 1000) {
4755 this.draw(false);
4756 return;
4757 }
4758 await this.particles.draw(delta);
4759 if (!this.alive()) {
4760 this.destroy();
4761 return;
4762 }
4763 if (this.getAnimationStatus()) {
4764 this.draw(false);
4765 }
4766 } catch (e) {
4767 getLogger().error(`${errorPrefix} in animation loop`, e);
4768 }
4769 };
4770 this._engine = engine;
4771 this.fpsLimit = 120;
4772 this.smooth = false;
4773 this._delay = 0;
4774 this._duration = 0;
4775 this._lifeTime = 0;
4776 this._firstStart = true;
4777 this.started = false;
4778 this.destroyed = false;
4779 this._paused = true;
4780 this.lastFrameTime = 0;
4781 this.zLayers = 100;
4782 this.pageHidden = false;
4783 this._sourceOptions = sourceOptions;
4784 this._initialSourceOptions = sourceOptions;
4785 this.retina = new Retina(this);
4786 this.canvas = new Canvas(this);
4787 this.particles = new Particles(this._engine, this);
4788 this.pathGenerators = new Map();
4789 this.interactivity = {
4790 mouse: {
4791 clicking: false,
4792 inside: false
4793 }
4794 };
4795 this.plugins = new Map();
4796 this.drawers = new Map();
4797 this._options = loadContainerOptions(this._engine, this);
4798 this.actualOptions = loadContainerOptions(this._engine, this);
4799 this._eventListeners = new EventListeners(this);
4800 if (typeof IntersectionObserver !== "undefined" && IntersectionObserver) {
4801 this._intersectionObserver = new IntersectionObserver(entries => this._intersectionManager(entries));
4802 }
4803 this._engine.dispatchEvent("containerBuilt", {
4804 container: this
4805 });
4806 }
4807 get options() {
4808 return this._options;
4809 }
4810 get sourceOptions() {
4811 return this._sourceOptions;
4812 }
4813 addClickHandler(callback) {
4814 if (!guardCheck(this)) {
4815 return;
4816 }
4817 const el = this.interactivity.element;
4818 if (!el) {
4819 return;
4820 }
4821 const clickOrTouchHandler = (e, pos, radius) => {
4822 if (!guardCheck(this)) {
4823 return;
4824 }
4825 const pxRatio = this.retina.pixelRatio,
4826 posRetina = {
4827 x: pos.x * pxRatio,
4828 y: pos.y * pxRatio
4829 },
4830 particles = this.particles.quadTree.queryCircle(posRetina, radius * pxRatio);
4831 callback(e, particles);
4832 };
4833 const clickHandler = e => {
4834 if (!guardCheck(this)) {
4835 return;
4836 }
4837 const mouseEvent = e,
4838 pos = {
4839 x: mouseEvent.offsetX || mouseEvent.clientX,
4840 y: mouseEvent.offsetY || mouseEvent.clientY
4841 };
4842 clickOrTouchHandler(e, pos, 1);
4843 };
4844 const touchStartHandler = () => {
4845 if (!guardCheck(this)) {
4846 return;
4847 }
4848 touched = true;
4849 touchMoved = false;
4850 };
4851 const touchMoveHandler = () => {
4852 if (!guardCheck(this)) {
4853 return;
4854 }
4855 touchMoved = true;
4856 };
4857 const touchEndHandler = e => {
4858 if (!guardCheck(this)) {
4859 return;
4860 }
4861 if (touched && !touchMoved) {
4862 const touchEvent = e;
4863 let lastTouch = touchEvent.touches[touchEvent.touches.length - 1];
4864 if (!lastTouch) {
4865 lastTouch = touchEvent.changedTouches[touchEvent.changedTouches.length - 1];
4866 if (!lastTouch) {
4867 return;
4868 }
4869 }
4870 const element = this.canvas.element,
4871 canvasRect = element ? element.getBoundingClientRect() : undefined,
4872 pos = {
4873 x: lastTouch.clientX - (canvasRect ? canvasRect.left : 0),
4874 y: lastTouch.clientY - (canvasRect ? canvasRect.top : 0)
4875 };
4876 clickOrTouchHandler(e, pos, Math.max(lastTouch.radiusX, lastTouch.radiusY));
4877 }
4878 touched = false;
4879 touchMoved = false;
4880 };
4881 const touchCancelHandler = () => {
4882 if (!guardCheck(this)) {
4883 return;
4884 }
4885 touched = false;
4886 touchMoved = false;
4887 };
4888 let touched = false,
4889 touchMoved = false;
4890 el.addEventListener("click", clickHandler);
4891 el.addEventListener("touchstart", touchStartHandler);
4892 el.addEventListener("touchmove", touchMoveHandler);
4893 el.addEventListener("touchend", touchEndHandler);
4894 el.addEventListener("touchcancel", touchCancelHandler);
4895 }
4896 addLifeTime(value) {
4897 this._lifeTime += value;
4898 }
4899 addPath(key, generator, override = false) {
4900 if (!guardCheck(this) || !override && this.pathGenerators.has(key)) {
4901 return false;
4902 }
4903 this.pathGenerators.set(key, generator ?? defaultPathGenerator);
4904 return true;
4905 }
4906 alive() {
4907 return !this._duration || this._lifeTime <= this._duration;
4908 }
4909 destroy() {
4910 if (!guardCheck(this)) {
4911 return;
4912 }
4913 this.stop();
4914 this.particles.destroy();
4915 this.canvas.destroy();
4916 for (const [, drawer] of this.drawers) {
4917 drawer.destroy && drawer.destroy(this);
4918 }
4919 for (const key of this.drawers.keys()) {
4920 this.drawers.delete(key);
4921 }
4922 this._engine.plugins.destroy(this);
4923 this.destroyed = true;
4924 const mainArr = this._engine.dom(),
4925 idx = mainArr.findIndex(t => t === this);
4926 if (idx >= 0) {
4927 mainArr.splice(idx, 1);
4928 }
4929 this._engine.dispatchEvent("containerDestroyed", {
4930 container: this
4931 });
4932 }
4933 draw(force) {
4934 if (!guardCheck(this)) {
4935 return;
4936 }
4937 let refreshTime = force;
4938 this._drawAnimationFrame = requestAnimationFrame(async timestamp => {
4939 if (refreshTime) {
4940 this.lastFrameTime = undefined;
4941 refreshTime = false;
4942 }
4943 await this._nextFrame(timestamp);
4944 });
4945 }
4946 async export(type, options = {}) {
4947 for (const [, plugin] of this.plugins) {
4948 if (!plugin.export) {
4949 continue;
4950 }
4951 const res = await plugin.export(type, options);
4952 if (!res.supported) {
4953 continue;
4954 }
4955 return res.blob;
4956 }
4957 getLogger().error(`${errorPrefix} - Export plugin with type ${type} not found`);
4958 }
4959 getAnimationStatus() {
4960 return !this._paused && !this.pageHidden && guardCheck(this);
4961 }
4962 handleClickMode(mode) {
4963 if (!guardCheck(this)) {
4964 return;
4965 }
4966 this.particles.handleClickMode(mode);
4967 for (const [, plugin] of this.plugins) {
4968 plugin.handleClickMode && plugin.handleClickMode(mode);
4969 }
4970 }
4971 async init() {
4972 if (!guardCheck(this)) {
4973 return;
4974 }
4975 const shapes = this._engine.plugins.getSupportedShapes();
4976 for (const type of shapes) {
4977 const drawer = this._engine.plugins.getShapeDrawer(type);
4978 if (drawer) {
4979 this.drawers.set(type, drawer);
4980 }
4981 }
4982 this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
4983 this.actualOptions = loadContainerOptions(this._engine, this, this._options);
4984 const availablePlugins = this._engine.plugins.getAvailablePlugins(this);
4985 for (const [id, plugin] of availablePlugins) {
4986 this.plugins.set(id, plugin);
4987 }
4988 this.retina.init();
4989 await this.canvas.init();
4990 this.updateActualOptions();
4991 this.canvas.initBackground();
4992 this.canvas.resize();
4993 this.zLayers = this.actualOptions.zLayers;
4994 this._duration = getRangeValue(this.actualOptions.duration) * 1000;
4995 this._delay = getRangeValue(this.actualOptions.delay) * 1000;
4996 this._lifeTime = 0;
4997 this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 120;
4998 this.smooth = this.actualOptions.smooth;
4999 for (const [, drawer] of this.drawers) {
5000 drawer.init && (await drawer.init(this));
5001 }
5002 for (const [, plugin] of this.plugins) {
5003 plugin.init && (await plugin.init());
5004 }
5005 this._engine.dispatchEvent("containerInit", {
5006 container: this
5007 });
5008 this.particles.init();
5009 this.particles.setDensity();
5010 for (const [, plugin] of this.plugins) {
5011 plugin.particlesSetup && plugin.particlesSetup();
5012 }
5013 this._engine.dispatchEvent("particlesSetup", {
5014 container: this
5015 });
5016 }
5017 async loadTheme(name) {
5018 if (!guardCheck(this)) {
5019 return;
5020 }
5021 this._currentTheme = name;
5022 await this.refresh();
5023 }
5024 pause() {
5025 if (!guardCheck(this)) {
5026 return;
5027 }
5028 if (this._drawAnimationFrame !== undefined) {
5029 cancelAnimationFrame(this._drawAnimationFrame);
5030 delete this._drawAnimationFrame;
5031 }
5032 if (this._paused) {
5033 return;
5034 }
5035 for (const [, plugin] of this.plugins) {
5036 plugin.pause && plugin.pause();
5037 }
5038 if (!this.pageHidden) {
5039 this._paused = true;
5040 }
5041 this._engine.dispatchEvent("containerPaused", {
5042 container: this
5043 });
5044 }
5045 play(force) {
5046 if (!guardCheck(this)) {
5047 return;
5048 }
5049 const needsUpdate = this._paused || force;
5050 if (this._firstStart && !this.actualOptions.autoPlay) {
5051 this._firstStart = false;
5052 return;
5053 }
5054 if (this._paused) {
5055 this._paused = false;
5056 }
5057 if (needsUpdate) {
5058 for (const [, plugin] of this.plugins) {
5059 if (plugin.play) {
5060 plugin.play();
5061 }
5062 }
5063 }
5064 this._engine.dispatchEvent("containerPlay", {
5065 container: this
5066 });
5067 this.draw(needsUpdate || false);
5068 }
5069 async refresh() {
5070 if (!guardCheck(this)) {
5071 return;
5072 }
5073 this.stop();
5074 return this.start();
5075 }
5076 async reset() {
5077 if (!guardCheck(this)) {
5078 return;
5079 }
5080 this._initialSourceOptions = undefined;
5081 this._options = loadContainerOptions(this._engine, this);
5082 this.actualOptions = loadContainerOptions(this._engine, this, this._options);
5083 return this.refresh();
5084 }
5085 setNoise(noiseOrGenerator, init, update) {
5086 if (!guardCheck(this)) {
5087 return;
5088 }
5089 this.setPath(noiseOrGenerator, init, update);
5090 }
5091 setPath(pathOrGenerator, init, update) {
5092 if (!pathOrGenerator || !guardCheck(this)) {
5093 return;
5094 }
5095 const pathGenerator = {
5096 ...defaultPathGenerator
5097 };
5098 if (isFunction(pathOrGenerator)) {
5099 pathGenerator.generate = pathOrGenerator;
5100 if (init) {
5101 pathGenerator.init = init;
5102 }
5103 if (update) {
5104 pathGenerator.update = update;
5105 }
5106 } else {
5107 const oldGenerator = pathGenerator;
5108 pathGenerator.generate = pathOrGenerator.generate || oldGenerator.generate;
5109 pathGenerator.init = pathOrGenerator.init || oldGenerator.init;
5110 pathGenerator.update = pathOrGenerator.update || oldGenerator.update;
5111 }
5112 this.addPath(defaultPathGeneratorKey, pathGenerator, true);
5113 }
5114 async start() {
5115 if (!guardCheck(this) || this.started) {
5116 return;
5117 }
5118 await this.init();
5119 this.started = true;
5120 await new Promise(resolve => {
5121 this._delayTimeout = setTimeout(async () => {
5122 this._eventListeners.addListeners();
5123 if (this.interactivity.element instanceof HTMLElement && this._intersectionObserver) {
5124 this._intersectionObserver.observe(this.interactivity.element);
5125 }
5126 for (const [, plugin] of this.plugins) {
5127 plugin.start && (await plugin.start());
5128 }
5129 this._engine.dispatchEvent("containerStarted", {
5130 container: this
5131 });
5132 this.play();
5133 resolve();
5134 }, this._delay);
5135 });
5136 }
5137 stop() {
5138 if (!guardCheck(this) || !this.started) {
5139 return;
5140 }
5141 if (this._delayTimeout) {
5142 clearTimeout(this._delayTimeout);
5143 delete this._delayTimeout;
5144 }
5145 this._firstStart = true;
5146 this.started = false;
5147 this._eventListeners.removeListeners();
5148 this.pause();
5149 this.particles.clear();
5150 this.canvas.stop();
5151 if (this.interactivity.element instanceof HTMLElement && this._intersectionObserver) {
5152 this._intersectionObserver.unobserve(this.interactivity.element);
5153 }
5154 for (const [, plugin] of this.plugins) {
5155 plugin.stop && plugin.stop();
5156 }
5157 for (const key of this.plugins.keys()) {
5158 this.plugins.delete(key);
5159 }
5160 this._sourceOptions = this._options;
5161 this._engine.dispatchEvent("containerStopped", {
5162 container: this
5163 });
5164 }
5165 updateActualOptions() {
5166 this.actualOptions.responsive = [];
5167 const newMaxWidth = this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
5168 this.actualOptions.setTheme(this._currentTheme);
5169 if (this.responsiveMaxWidth === newMaxWidth) {
5170 return false;
5171 }
5172 this.responsiveMaxWidth = newMaxWidth;
5173 return true;
5174 }
5175}
5176;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/EventDispatcher.js
5177class EventDispatcher {
5178 constructor() {
5179 this._listeners = new Map();
5180 }
5181 addEventListener(type, listener) {
5182 this.removeEventListener(type, listener);
5183 let arr = this._listeners.get(type);
5184 if (!arr) {
5185 arr = [];
5186 this._listeners.set(type, arr);
5187 }
5188 arr.push(listener);
5189 }
5190 dispatchEvent(type, args) {
5191 const listeners = this._listeners.get(type);
5192 listeners && listeners.forEach(handler => handler(args));
5193 }
5194 hasEventListener(type) {
5195 return !!this._listeners.get(type);
5196 }
5197 removeAllEventListeners(type) {
5198 if (!type) {
5199 this._listeners = new Map();
5200 } else {
5201 this._listeners.delete(type);
5202 }
5203 }
5204 removeEventListener(type, listener) {
5205 const arr = this._listeners.get(type);
5206 if (!arr) {
5207 return;
5208 }
5209 const length = arr.length,
5210 idx = arr.indexOf(listener);
5211 if (idx < 0) {
5212 return;
5213 }
5214 if (length === 1) {
5215 this._listeners.delete(type);
5216 } else {
5217 arr.splice(idx, 1);
5218 }
5219 }
5220}
5221;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Plugins.js
5222
5223function getItemsFromInitializer(container, map, initializers, force = false) {
5224 let res = map.get(container);
5225 if (!res || force) {
5226 res = [...initializers.values()].map(t => t(container));
5227 map.set(container, res);
5228 }
5229 return res;
5230}
5231class Plugins {
5232 constructor(engine) {
5233 this._engine = engine;
5234 this.plugins = [];
5235 this._initializers = {
5236 interactors: new Map(),
5237 movers: new Map(),
5238 updaters: new Map()
5239 };
5240 this.interactors = new Map();
5241 this.movers = new Map();
5242 this.updaters = new Map();
5243 this.presets = new Map();
5244 this.drawers = new Map();
5245 this.pathGenerators = new Map();
5246 }
5247 addInteractor(name, initInteractor) {
5248 this._initializers.interactors.set(name, initInteractor);
5249 }
5250 addParticleMover(name, initMover) {
5251 this._initializers.movers.set(name, initMover);
5252 }
5253 addParticleUpdater(name, initUpdater) {
5254 this._initializers.updaters.set(name, initUpdater);
5255 }
5256 addPathGenerator(type, pathGenerator) {
5257 !this.getPathGenerator(type) && this.pathGenerators.set(type, pathGenerator);
5258 }
5259 addPlugin(plugin) {
5260 !this.getPlugin(plugin.id) && this.plugins.push(plugin);
5261 }
5262 addPreset(presetKey, options, override = false) {
5263 (override || !this.getPreset(presetKey)) && this.presets.set(presetKey, options);
5264 }
5265 addShapeDrawer(types, drawer) {
5266 executeOnSingleOrMultiple(types, type => {
5267 !this.getShapeDrawer(type) && this.drawers.set(type, drawer);
5268 });
5269 }
5270 destroy(container) {
5271 this.updaters.delete(container);
5272 this.movers.delete(container);
5273 this.interactors.delete(container);
5274 }
5275 getAvailablePlugins(container) {
5276 const res = new Map();
5277 for (const plugin of this.plugins) {
5278 plugin.needsPlugin(container.actualOptions) && res.set(plugin.id, plugin.getPlugin(container));
5279 }
5280 return res;
5281 }
5282 getInteractors(container, force = false) {
5283 return getItemsFromInitializer(container, this.interactors, this._initializers.interactors, force);
5284 }
5285 getMovers(container, force = false) {
5286 return getItemsFromInitializer(container, this.movers, this._initializers.movers, force);
5287 }
5288 getPathGenerator(type) {
5289 return this.pathGenerators.get(type);
5290 }
5291 getPlugin(plugin) {
5292 return this.plugins.find(t => t.id === plugin);
5293 }
5294 getPreset(preset) {
5295 return this.presets.get(preset);
5296 }
5297 getShapeDrawer(type) {
5298 return this.drawers.get(type);
5299 }
5300 getSupportedShapes() {
5301 return this.drawers.keys();
5302 }
5303 getUpdaters(container, force = false) {
5304 return getItemsFromInitializer(container, this.updaters, this._initializers.updaters, force);
5305 }
5306 loadOptions(options, sourceOptions) {
5307 for (const plugin of this.plugins) {
5308 plugin.loadOptions(options, sourceOptions);
5309 }
5310 }
5311 loadParticlesOptions(container, options, ...sourceOptions) {
5312 const updaters = this.updaters.get(container);
5313 if (!updaters) {
5314 return;
5315 }
5316 for (const updater of updaters) {
5317 updater.loadOptions && updater.loadOptions(options, ...sourceOptions);
5318 }
5319 }
5320}
5321;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Engine.js
5322
5323
5324
5325
5326
5327
5328async function getDataFromUrl(data) {
5329 const url = itemFromSingleOrMultiple(data.url, data.index);
5330 if (!url) {
5331 return data.fallback;
5332 }
5333 const response = await fetch(url);
5334 if (response.ok) {
5335 return response.json();
5336 }
5337 getLogger().error(`${errorPrefix} ${response.status} while retrieving config file`);
5338 return data.fallback;
5339}
5340function isParamsEmpty(params) {
5341 return !params.id && !params.element && !params.url && !params.options;
5342}
5343function isParams(obj) {
5344 return !isParamsEmpty(obj);
5345}
5346class Engine {
5347 constructor() {
5348 this._configs = new Map();
5349 this._domArray = [];
5350 this._eventDispatcher = new EventDispatcher();
5351 this._initialized = false;
5352 this.plugins = new Plugins(this);
5353 }
5354 get configs() {
5355 const res = {};
5356 for (const [name, config] of this._configs) {
5357 res[name] = config;
5358 }
5359 return res;
5360 }
5361 get version() {
5362 return "2.12.0";
5363 }
5364 addConfig(nameOrConfig, config) {
5365 if (isString(nameOrConfig)) {
5366 if (config) {
5367 config.name = nameOrConfig;
5368 this._configs.set(nameOrConfig, config);
5369 }
5370 } else {
5371 this._configs.set(nameOrConfig.name ?? "default", nameOrConfig);
5372 }
5373 }
5374 addEventListener(type, listener) {
5375 this._eventDispatcher.addEventListener(type, listener);
5376 }
5377 async addInteractor(name, interactorInitializer, refresh = true) {
5378 this.plugins.addInteractor(name, interactorInitializer);
5379 await this.refresh(refresh);
5380 }
5381 async addMover(name, moverInitializer, refresh = true) {
5382 this.plugins.addParticleMover(name, moverInitializer);
5383 await this.refresh(refresh);
5384 }
5385 async addParticleUpdater(name, updaterInitializer, refresh = true) {
5386 this.plugins.addParticleUpdater(name, updaterInitializer);
5387 await this.refresh(refresh);
5388 }
5389 async addPathGenerator(name, generator, refresh = true) {
5390 this.plugins.addPathGenerator(name, generator);
5391 await this.refresh(refresh);
5392 }
5393 async addPlugin(plugin, refresh = true) {
5394 this.plugins.addPlugin(plugin);
5395 await this.refresh(refresh);
5396 }
5397 async addPreset(preset, options, override = false, refresh = true) {
5398 this.plugins.addPreset(preset, options, override);
5399 await this.refresh(refresh);
5400 }
5401 async addShape(shape, drawer, initOrRefresh, afterEffectOrRefresh, destroyOrRefresh, refresh = true) {
5402 let customDrawer;
5403 let realRefresh = refresh,
5404 realInit,
5405 realAfterEffect,
5406 realDestroy;
5407 if (isBoolean(initOrRefresh)) {
5408 realRefresh = initOrRefresh;
5409 realInit = undefined;
5410 } else {
5411 realInit = initOrRefresh;
5412 }
5413 if (isBoolean(afterEffectOrRefresh)) {
5414 realRefresh = afterEffectOrRefresh;
5415 realAfterEffect = undefined;
5416 } else {
5417 realAfterEffect = afterEffectOrRefresh;
5418 }
5419 if (isBoolean(destroyOrRefresh)) {
5420 realRefresh = destroyOrRefresh;
5421 realDestroy = undefined;
5422 } else {
5423 realDestroy = destroyOrRefresh;
5424 }
5425 if (isFunction(drawer)) {
5426 customDrawer = {
5427 afterEffect: realAfterEffect,
5428 destroy: realDestroy,
5429 draw: drawer,
5430 init: realInit
5431 };
5432 } else {
5433 customDrawer = drawer;
5434 }
5435 this.plugins.addShapeDrawer(shape, customDrawer);
5436 await this.refresh(realRefresh);
5437 }
5438 dispatchEvent(type, args) {
5439 this._eventDispatcher.dispatchEvent(type, args);
5440 }
5441 dom() {
5442 return this._domArray;
5443 }
5444 domItem(index) {
5445 const dom = this.dom(),
5446 item = dom[index];
5447 if (!item || item.destroyed) {
5448 dom.splice(index, 1);
5449 return;
5450 }
5451 return item;
5452 }
5453 init() {
5454 if (this._initialized) {
5455 return;
5456 }
5457 this._initialized = true;
5458 }
5459 async load(tagIdOrOptionsOrParams, options) {
5460 return this.loadFromArray(tagIdOrOptionsOrParams, options);
5461 }
5462 async loadFromArray(tagIdOrOptionsOrParams, optionsOrIndex, index) {
5463 let params;
5464 if (!isParams(tagIdOrOptionsOrParams)) {
5465 params = {};
5466 if (isString(tagIdOrOptionsOrParams)) {
5467 params.id = tagIdOrOptionsOrParams;
5468 } else {
5469 params.options = tagIdOrOptionsOrParams;
5470 }
5471 if (isNumber(optionsOrIndex)) {
5472 params.index = optionsOrIndex;
5473 } else {
5474 params.options = optionsOrIndex ?? params.options;
5475 }
5476 params.index = index ?? params.index;
5477 } else {
5478 params = tagIdOrOptionsOrParams;
5479 }
5480 return this._loadParams(params);
5481 }
5482 async loadJSON(tagId, pathConfigJson, index) {
5483 let url, id;
5484 if (isNumber(pathConfigJson) || pathConfigJson === undefined) {
5485 url = tagId;
5486 } else {
5487 id = tagId;
5488 url = pathConfigJson;
5489 }
5490 return this._loadParams({
5491 id: id,
5492 url,
5493 index
5494 });
5495 }
5496 async refresh(refresh = true) {
5497 if (!refresh) {
5498 return;
5499 }
5500 this.dom().forEach(t => t.refresh());
5501 }
5502 removeEventListener(type, listener) {
5503 this._eventDispatcher.removeEventListener(type, listener);
5504 }
5505 async set(id, element, options, index) {
5506 const params = {
5507 index
5508 };
5509 if (isString(id)) {
5510 params.id = id;
5511 } else {
5512 params.element = id;
5513 }
5514 if (element instanceof HTMLElement) {
5515 params.element = element;
5516 } else {
5517 params.options = element;
5518 }
5519 if (isNumber(options)) {
5520 params.index = options;
5521 } else {
5522 params.options = options ?? params.options;
5523 }
5524 return this._loadParams(params);
5525 }
5526 async setJSON(id, element, pathConfigJson, index) {
5527 const params = {};
5528 if (id instanceof HTMLElement) {
5529 params.element = id;
5530 params.url = element;
5531 params.index = pathConfigJson;
5532 } else {
5533 params.id = id;
5534 params.element = element;
5535 params.url = pathConfigJson;
5536 params.index = index;
5537 }
5538 return this._loadParams(params);
5539 }
5540 setOnClickHandler(callback) {
5541 const dom = this.dom();
5542 if (!dom.length) {
5543 throw new Error(`${errorPrefix} can only set click handlers after calling tsParticles.load()`);
5544 }
5545 for (const domItem of dom) {
5546 domItem.addClickHandler(callback);
5547 }
5548 }
5549 async _loadParams(params) {
5550 const id = params.id ?? `tsparticles${Math.floor(getRandom() * 10000)}`,
5551 {
5552 index,
5553 url
5554 } = params,
5555 options = url ? await getDataFromUrl({
5556 fallback: params.options,
5557 url,
5558 index
5559 }) : params.options;
5560 let domContainer = params.element ?? document.getElementById(id);
5561 if (!domContainer) {
5562 domContainer = document.createElement("div");
5563 domContainer.id = id;
5564 document.body.append(domContainer);
5565 }
5566 const currentOptions = itemFromSingleOrMultiple(options, index),
5567 dom = this.dom(),
5568 oldIndex = dom.findIndex(v => v.id === id);
5569 if (oldIndex >= 0) {
5570 const old = this.domItem(oldIndex);
5571 if (old && !old.destroyed) {
5572 old.destroy();
5573 dom.splice(oldIndex, 1);
5574 }
5575 }
5576 let canvasEl;
5577 if (domContainer.tagName.toLowerCase() === "canvas") {
5578 canvasEl = domContainer;
5579 canvasEl.dataset[generatedAttribute] = "false";
5580 } else {
5581 const existingCanvases = domContainer.getElementsByTagName("canvas");
5582 if (existingCanvases.length) {
5583 canvasEl = existingCanvases[0];
5584 canvasEl.dataset[generatedAttribute] = "false";
5585 } else {
5586 canvasEl = document.createElement("canvas");
5587 canvasEl.dataset[generatedAttribute] = "true";
5588 domContainer.appendChild(canvasEl);
5589 }
5590 }
5591 if (!canvasEl.style.width) {
5592 canvasEl.style.width = "100%";
5593 }
5594 if (!canvasEl.style.height) {
5595 canvasEl.style.height = "100%";
5596 }
5597 const newItem = new Container(this, id, currentOptions);
5598 if (oldIndex >= 0) {
5599 dom.splice(oldIndex, 0, newItem);
5600 } else {
5601 dom.push(newItem);
5602 }
5603 newItem.canvas.loadCanvas(canvasEl);
5604 await newItem.start();
5605 return newItem;
5606 }
5607}
5608;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/HslColorManager.js
5609
5610
5611class HslColorManager {
5612 constructor() {
5613 this.key = "hsl";
5614 this.stringPrefix = "hsl";
5615 }
5616 handleColor(color) {
5617 const colorValue = color.value,
5618 hslColor = colorValue.hsl ?? color.value;
5619 if (hslColor.h !== undefined && hslColor.s !== undefined && hslColor.l !== undefined) {
5620 return hslToRgb(hslColor);
5621 }
5622 }
5623 handleRangeColor(color) {
5624 const colorValue = color.value,
5625 hslColor = colorValue.hsl ?? color.value;
5626 if (hslColor.h !== undefined && hslColor.l !== undefined) {
5627 return hslToRgb({
5628 h: getRangeValue(hslColor.h),
5629 l: getRangeValue(hslColor.l),
5630 s: getRangeValue(hslColor.s)
5631 });
5632 }
5633 }
5634 parseString(input) {
5635 if (!input.startsWith("hsl")) {
5636 return;
5637 }
5638 const regex = /hsla?\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*(,\s*([\d.%]+)\s*)?\)/i,
5639 result = regex.exec(input);
5640 return result ? hslaToRgba({
5641 a: result.length > 4 ? parseAlpha(result[5]) : 1,
5642 h: parseInt(result[1], 10),
5643 l: parseInt(result[3], 10),
5644 s: parseInt(result[2], 10)
5645 }) : undefined;
5646 }
5647}
5648;// CONCATENATED MODULE: ../../engine/dist/esm/Utils/RgbColorManager.js
5649
5650class RgbColorManager {
5651 constructor() {
5652 this.key = "rgb";
5653 this.stringPrefix = "rgb";
5654 }
5655 handleColor(color) {
5656 const colorValue = color.value,
5657 rgbColor = colorValue.rgb ?? color.value;
5658 if (rgbColor.r !== undefined) {
5659 return rgbColor;
5660 }
5661 }
5662 handleRangeColor(color) {
5663 const colorValue = color.value,
5664 rgbColor = colorValue.rgb ?? color.value;
5665 if (rgbColor.r !== undefined) {
5666 return {
5667 r: getRangeValue(rgbColor.r),
5668 g: getRangeValue(rgbColor.g),
5669 b: getRangeValue(rgbColor.b)
5670 };
5671 }
5672 }
5673 parseString(input) {
5674 if (!input.startsWith(this.stringPrefix)) {
5675 return;
5676 }
5677 const regex = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([\d.%]+)\s*)?\)/i,
5678 result = regex.exec(input);
5679 return result ? {
5680 a: result.length > 4 ? parseAlpha(result[5]) : 1,
5681 b: parseInt(result[3], 10),
5682 g: parseInt(result[2], 10),
5683 r: parseInt(result[1], 10)
5684 } : undefined;
5685 }
5686}
5687;// CONCATENATED MODULE: ../../engine/dist/esm/init.js
5688
5689
5690
5691
5692function init() {
5693 const rgbColorManager = new RgbColorManager(),
5694 hslColorManager = new HslColorManager();
5695 addColorManager(rgbColorManager);
5696 addColorManager(hslColorManager);
5697 const engine = new Engine();
5698 engine.init();
5699 return engine;
5700}
5701;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/ExternalInteractorBase.js
5702class ExternalInteractorBase {
5703 constructor(container) {
5704 this.container = container;
5705 this.type = "external";
5706 }
5707}
5708;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/ParticlesInteractorBase.js
5709class ParticlesInteractorBase {
5710 constructor(container) {
5711 this.container = container;
5712 this.type = "particles";
5713 }
5714}
5715;// CONCATENATED MODULE: ../../engine/dist/esm/exports.js
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805;// CONCATENATED MODULE: ../../engine/dist/esm/index.js
5806
5807
5808const tsParticles = init();
5809if (!isSsr()) {
5810 window.tsParticles = tsParticles;
5811}
5812
5813
5814
5815;// CONCATENATED MODULE: ../pjs/dist/esm/marcbruederlin/Particles.js
5816
5817class Particles_Particles {
5818 static init(options) {
5819 const particles = new Particles_Particles(),
5820 selector = options.selector;
5821 if (!selector) {
5822 throw new Error("No selector provided");
5823 }
5824 const el = document.querySelector(selector);
5825 if (!el) {
5826 throw new Error("No element found for selector");
5827 }
5828 tsParticles.set(selector.replace(".", "").replace("!", ""), el, {
5829 fullScreen: {
5830 enable: false
5831 },
5832 particles: {
5833 color: {
5834 value: options.color ?? "!000000"
5835 },
5836 links: {
5837 color: "random",
5838 distance: options.minDistance ?? 120,
5839 enable: options.connectParticles ?? false
5840 },
5841 move: {
5842 enable: true,
5843 speed: options.speed ?? 0.5
5844 },
5845 number: {
5846 value: options.maxParticles ?? 100
5847 },
5848 size: {
5849 value: {
5850 min: 1,
5851 max: options.sizeVariations ?? 3
5852 }
5853 }
5854 },
5855 responsive: options.responsive?.map(responsive => ({
5856 maxWidth: responsive.breakpoint,
5857 options: {
5858 particles: {
5859 color: {
5860 value: responsive.options?.color
5861 },
5862 links: {
5863 distance: responsive.options?.minDistance,
5864 enable: responsive.options?.connectParticles
5865 },
5866 number: {
5867 value: options.maxParticles
5868 },
5869 move: {
5870 enable: true,
5871 speed: responsive.options?.speed
5872 },
5873 size: {
5874 value: responsive.options?.sizeVariations
5875 }
5876 }
5877 }
5878 }))
5879 }).then(container => {
5880 particles._container = container;
5881 });
5882 return particles;
5883 }
5884 destroy() {
5885 const container = this._container;
5886 container && container.destroy();
5887 }
5888 pauseAnimation() {
5889 const container = this._container;
5890 container && container.pause();
5891 }
5892 resumeAnimation() {
5893 const container = this._container;
5894 container && container.play();
5895 }
5896}
5897;// CONCATENATED MODULE: ../pjs/dist/esm/VincentGarreau/particles.js
5898const initParticlesJS = engine => {
5899 const particlesJS = (tagId, options) => {
5900 return engine.load(tagId, options);
5901 };
5902 particlesJS.load = (tagId, pathConfigJson, callback) => {
5903 engine.loadJSON(tagId, pathConfigJson).then(container => {
5904 if (container) {
5905 callback(container);
5906 }
5907 }).catch(() => {
5908 callback(undefined);
5909 });
5910 };
5911 particlesJS.setOnClickHandler = callback => {
5912 engine.setOnClickHandler(callback);
5913 };
5914 const pJSDom = engine.dom();
5915 return {
5916 particlesJS,
5917 pJSDom
5918 };
5919};
5920
5921;// CONCATENATED MODULE: ../pjs/dist/esm/index.js
5922
5923
5924const initPjs = engine => {
5925 const {
5926 particlesJS,
5927 pJSDom
5928 } = initParticlesJS(engine);
5929 window.particlesJS = particlesJS;
5930 window.pJSDom = pJSDom;
5931 window.Particles = Particles_Particles;
5932 return {
5933 particlesJS,
5934 pJSDom,
5935 Particles: Particles_Particles
5936 };
5937};
5938
5939;// CONCATENATED MODULE: ../../move/base/dist/esm/Utils.js
5940
5941function applyDistance(particle) {
5942 const initialPosition = particle.initialPosition,
5943 {
5944 dx,
5945 dy
5946 } = getDistances(initialPosition, particle.position),
5947 dxFixed = Math.abs(dx),
5948 dyFixed = Math.abs(dy),
5949 {
5950 maxDistance
5951 } = particle.retina,
5952 hDistance = maxDistance.horizontal,
5953 vDistance = maxDistance.vertical;
5954 if (!hDistance && !vDistance) {
5955 return;
5956 }
5957 if ((hDistance && dxFixed >= hDistance || vDistance && dyFixed >= vDistance) && !particle.misplaced) {
5958 particle.misplaced = !!hDistance && dxFixed > hDistance || !!vDistance && dyFixed > vDistance;
5959 if (hDistance) {
5960 particle.velocity.x = particle.velocity.y / 2 - particle.velocity.x;
5961 }
5962 if (vDistance) {
5963 particle.velocity.y = particle.velocity.x / 2 - particle.velocity.y;
5964 }
5965 } else if ((!hDistance || dxFixed < hDistance) && (!vDistance || dyFixed < vDistance) && particle.misplaced) {
5966 particle.misplaced = false;
5967 } else if (particle.misplaced) {
5968 const pos = particle.position,
5969 vel = particle.velocity;
5970 if (hDistance && (pos.x < initialPosition.x && vel.x < 0 || pos.x > initialPosition.x && vel.x > 0)) {
5971 vel.x *= -getRandom();
5972 }
5973 if (vDistance && (pos.y < initialPosition.y && vel.y < 0 || pos.y > initialPosition.y && vel.y > 0)) {
5974 vel.y *= -getRandom();
5975 }
5976 }
5977}
5978function move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, delta) {
5979 applyPath(particle, delta);
5980 const gravityOptions = particle.gravity,
5981 gravityFactor = gravityOptions?.enable && gravityOptions.inverse ? -1 : 1;
5982 if (moveDrift && moveSpeed) {
5983 particle.velocity.x += moveDrift * delta.factor / (60 * moveSpeed);
5984 }
5985 if (gravityOptions?.enable && moveSpeed) {
5986 particle.velocity.y += gravityFactor * (gravityOptions.acceleration * delta.factor) / (60 * moveSpeed);
5987 }
5988 const decay = particle.moveDecay;
5989 particle.velocity.multTo(decay);
5990 const velocity = particle.velocity.mult(moveSpeed);
5991 if (gravityOptions?.enable && maxSpeed > 0 && (!gravityOptions.inverse && velocity.y >= 0 && velocity.y >= maxSpeed || gravityOptions.inverse && velocity.y <= 0 && velocity.y <= -maxSpeed)) {
5992 velocity.y = gravityFactor * maxSpeed;
5993 if (moveSpeed) {
5994 particle.velocity.y = velocity.y / moveSpeed;
5995 }
5996 }
5997 const zIndexOptions = particle.options.zIndex,
5998 zVelocityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.velocityRate;
5999 velocity.multTo(zVelocityFactor);
6000 const {
6001 position
6002 } = particle;
6003 position.addTo(velocity);
6004 if (moveOptions.vibrate) {
6005 position.x += Math.sin(position.x * Math.cos(position.y));
6006 position.y += Math.cos(position.y * Math.sin(position.x));
6007 }
6008}
6009function spin(particle, moveSpeed) {
6010 const container = particle.container;
6011 if (!particle.spin) {
6012 return;
6013 }
6014 const updateFunc = {
6015 x: particle.spin.direction === "clockwise" ? Math.cos : Math.sin,
6016 y: particle.spin.direction === "clockwise" ? Math.sin : Math.cos
6017 };
6018 particle.position.x = particle.spin.center.x + particle.spin.radius * updateFunc.x(particle.spin.angle);
6019 particle.position.y = particle.spin.center.y + particle.spin.radius * updateFunc.y(particle.spin.angle);
6020 particle.spin.radius += particle.spin.acceleration;
6021 const maxCanvasSize = Math.max(container.canvas.size.width, container.canvas.size.height);
6022 if (particle.spin.radius > maxCanvasSize / 2) {
6023 particle.spin.radius = maxCanvasSize / 2;
6024 particle.spin.acceleration *= -1;
6025 } else if (particle.spin.radius < 0) {
6026 particle.spin.radius = 0;
6027 particle.spin.acceleration *= -1;
6028 }
6029 particle.spin.angle += moveSpeed / 100 * (1 - particle.spin.radius / maxCanvasSize);
6030}
6031function applyPath(particle, delta) {
6032 const particlesOptions = particle.options,
6033 pathOptions = particlesOptions.move.path,
6034 pathEnabled = pathOptions.enable;
6035 if (!pathEnabled) {
6036 return;
6037 }
6038 if (particle.lastPathTime <= particle.pathDelay) {
6039 particle.lastPathTime += delta.value;
6040 return;
6041 }
6042 const path = particle.pathGenerator?.generate(particle, delta);
6043 if (path) {
6044 particle.velocity.addTo(path);
6045 }
6046 if (pathOptions.clamp) {
6047 particle.velocity.x = clamp(particle.velocity.x, -1, 1);
6048 particle.velocity.y = clamp(particle.velocity.y, -1, 1);
6049 }
6050 particle.lastPathTime -= particle.pathDelay;
6051}
6052function getProximitySpeedFactor(particle) {
6053 return particle.slow.inRange ? particle.slow.factor : 1;
6054}
6055;// CONCATENATED MODULE: ../../move/base/dist/esm/BaseMover.js
6056
6057
6058const diffFactor = 2;
6059class BaseMover {
6060 constructor() {
6061 this._initSpin = particle => {
6062 const container = particle.container,
6063 options = particle.options,
6064 spinOptions = options.move.spin;
6065 if (!spinOptions.enable) {
6066 return;
6067 }
6068 const spinPos = spinOptions.position ?? {
6069 x: 50,
6070 y: 50
6071 },
6072 spinCenter = {
6073 x: spinPos.x / 100 * container.canvas.size.width,
6074 y: spinPos.y / 100 * container.canvas.size.height
6075 },
6076 pos = particle.getPosition(),
6077 distance = getDistance(pos, spinCenter),
6078 spinAcceleration = getRangeValue(spinOptions.acceleration);
6079 particle.retina.spinAcceleration = spinAcceleration * container.retina.pixelRatio;
6080 particle.spin = {
6081 center: spinCenter,
6082 direction: particle.velocity.x >= 0 ? "clockwise" : "counter-clockwise",
6083 angle: particle.velocity.angle,
6084 radius: distance,
6085 acceleration: particle.retina.spinAcceleration
6086 };
6087 };
6088 }
6089 init(particle) {
6090 const options = particle.options,
6091 gravityOptions = options.move.gravity;
6092 particle.gravity = {
6093 enable: gravityOptions.enable,
6094 acceleration: getRangeValue(gravityOptions.acceleration),
6095 inverse: gravityOptions.inverse
6096 };
6097 this._initSpin(particle);
6098 }
6099 isEnabled(particle) {
6100 return !particle.destroyed && particle.options.move.enable;
6101 }
6102 move(particle, delta) {
6103 const particleOptions = particle.options,
6104 moveOptions = particleOptions.move;
6105 if (!moveOptions.enable) {
6106 return;
6107 }
6108 const container = particle.container,
6109 pxRatio = container.retina.pixelRatio,
6110 slowFactor = getProximitySpeedFactor(particle),
6111 baseSpeed = (particle.retina.moveSpeed ??= getRangeValue(moveOptions.speed) * pxRatio) * container.retina.reduceFactor,
6112 moveDrift = particle.retina.moveDrift ??= getRangeValue(particle.options.move.drift) * pxRatio,
6113 maxSize = getRangeMax(particleOptions.size.value) * pxRatio,
6114 sizeFactor = moveOptions.size ? particle.getRadius() / maxSize : 1,
6115 moveSpeed = baseSpeed * sizeFactor * slowFactor * (delta.factor || 1) / diffFactor,
6116 maxSpeed = particle.retina.maxSpeed ?? container.retina.maxSpeed;
6117 if (moveOptions.spin.enable) {
6118 spin(particle, moveSpeed);
6119 } else {
6120 move(particle, moveOptions, moveSpeed, maxSpeed, moveDrift, delta);
6121 }
6122 applyDistance(particle);
6123 }
6124}
6125;// CONCATENATED MODULE: ../../move/base/dist/esm/index.js
6126
6127async function loadBaseMover(engine, refresh = true) {
6128 await engine.addMover("base", () => new BaseMover(), refresh);
6129}
6130;// CONCATENATED MODULE: ../../shapes/circle/dist/esm/CircleDrawer.js
6131
6132class CircleDrawer {
6133 draw(context, particle, radius) {
6134 if (!particle.circleRange) {
6135 particle.circleRange = {
6136 min: 0,
6137 max: Math.PI * 2
6138 };
6139 }
6140 const circleRange = particle.circleRange;
6141 context.arc(0, 0, radius, circleRange.min, circleRange.max, false);
6142 }
6143 getSidesCount() {
6144 return 12;
6145 }
6146 particleInit(container, particle) {
6147 const shapeData = particle.shapeData,
6148 angle = shapeData?.angle ?? {
6149 max: 360,
6150 min: 0
6151 };
6152 particle.circleRange = !isObject(angle) ? {
6153 min: 0,
6154 max: angle * Math.PI / 180
6155 } : {
6156 min: angle.min * Math.PI / 180,
6157 max: angle.max * Math.PI / 180
6158 };
6159 }
6160}
6161;// CONCATENATED MODULE: ../../shapes/circle/dist/esm/index.js
6162
6163async function loadCircleShape(engine, refresh = true) {
6164 await engine.addShape("circle", new CircleDrawer(), refresh);
6165}
6166;// CONCATENATED MODULE: ../../updaters/color/dist/esm/Utils.js
6167
6168function updateColorValue(delta, colorValue, valueAnimation, max, decrease) {
6169 if (!colorValue || !valueAnimation.enable || (colorValue.maxLoops ?? 0) > 0 && (colorValue.loops ?? 0) > (colorValue.maxLoops ?? 0)) {
6170 return;
6171 }
6172 if (!colorValue.time) {
6173 colorValue.time = 0;
6174 }
6175 if ((colorValue.delayTime ?? 0) > 0 && colorValue.time < (colorValue.delayTime ?? 0)) {
6176 colorValue.time += delta.value;
6177 }
6178 if ((colorValue.delayTime ?? 0) > 0 && colorValue.time < (colorValue.delayTime ?? 0)) {
6179 return;
6180 }
6181 const offset = randomInRange(valueAnimation.offset),
6182 velocity = (colorValue.velocity ?? 0) * delta.factor + offset * 3.6,
6183 decay = colorValue.decay ?? 1;
6184 if (!decrease || colorValue.status === "increasing") {
6185 colorValue.value += velocity;
6186 if (colorValue.value > max) {
6187 if (!colorValue.loops) {
6188 colorValue.loops = 0;
6189 }
6190 colorValue.loops++;
6191 if (decrease) {
6192 colorValue.status = "decreasing";
6193 colorValue.value -= colorValue.value % max;
6194 }
6195 }
6196 } else {
6197 colorValue.value -= velocity;
6198 if (colorValue.value < 0) {
6199 if (!colorValue.loops) {
6200 colorValue.loops = 0;
6201 }
6202 colorValue.loops++;
6203 colorValue.status = "increasing";
6204 colorValue.value += colorValue.value;
6205 }
6206 }
6207 if (colorValue.velocity && decay !== 1) {
6208 colorValue.velocity *= decay;
6209 }
6210 if (colorValue.value > max) {
6211 colorValue.value %= max;
6212 }
6213}
6214function updateColor(particle, delta) {
6215 const {
6216 h: hAnimation,
6217 s: sAnimation,
6218 l: lAnimation
6219 } = particle.options.color.animation,
6220 {
6221 color
6222 } = particle;
6223 if (!color) {
6224 return;
6225 }
6226 const {
6227 h,
6228 s,
6229 l
6230 } = color;
6231 if (h) {
6232 updateColorValue(delta, h, hAnimation, 360, false);
6233 }
6234 if (s) {
6235 updateColorValue(delta, s, sAnimation, 100, true);
6236 }
6237 if (l) {
6238 updateColorValue(delta, l, lAnimation, 100, true);
6239 }
6240}
6241;// CONCATENATED MODULE: ../../updaters/color/dist/esm/ColorUpdater.js
6242
6243
6244class ColorUpdater {
6245 constructor(container) {
6246 this.container = container;
6247 }
6248 init(particle) {
6249 const hslColor = rangeColorToHsl(particle.options.color, particle.id, particle.options.reduceDuplicates);
6250 if (hslColor) {
6251 particle.color = getHslAnimationFromHsl(hslColor, particle.options.color.animation, this.container.retina.reduceFactor);
6252 }
6253 }
6254 isEnabled(particle) {
6255 const {
6256 h: hAnimation,
6257 s: sAnimation,
6258 l: lAnimation
6259 } = particle.options.color.animation,
6260 {
6261 color
6262 } = particle;
6263 return !particle.destroyed && !particle.spawning && (color?.h.value !== undefined && hAnimation.enable || color?.s.value !== undefined && sAnimation.enable || color?.l.value !== undefined && lAnimation.enable);
6264 }
6265 update(particle, delta) {
6266 updateColor(particle, delta);
6267 }
6268}
6269;// CONCATENATED MODULE: ../../updaters/color/dist/esm/index.js
6270
6271async function loadColorUpdater(engine, refresh = true) {
6272 await engine.addParticleUpdater("color", container => new ColorUpdater(container), refresh);
6273}
6274;// CONCATENATED MODULE: ../../updaters/opacity/dist/esm/Utils.js
6275
6276function checkDestroy(particle, value, minValue, maxValue) {
6277 switch (particle.options.opacity.animation.destroy) {
6278 case "max":
6279 if (value >= maxValue) {
6280 particle.destroy();
6281 }
6282 break;
6283 case "min":
6284 if (value <= minValue) {
6285 particle.destroy();
6286 }
6287 break;
6288 }
6289}
6290function updateOpacity(particle, delta) {
6291 const data = particle.opacity;
6292 if (particle.destroyed || !data?.enable || (data.maxLoops ?? 0) > 0 && (data.loops ?? 0) > (data.maxLoops ?? 0)) {
6293 return;
6294 }
6295 const minValue = data.min,
6296 maxValue = data.max,
6297 decay = data.decay ?? 1;
6298 if (!data.time) {
6299 data.time = 0;
6300 }
6301 if ((data.delayTime ?? 0) > 0 && data.time < (data.delayTime ?? 0)) {
6302 data.time += delta.value;
6303 }
6304 if ((data.delayTime ?? 0) > 0 && data.time < (data.delayTime ?? 0)) {
6305 return;
6306 }
6307 switch (data.status) {
6308 case "increasing":
6309 if (data.value >= maxValue) {
6310 data.status = "decreasing";
6311 if (!data.loops) {
6312 data.loops = 0;
6313 }
6314 data.loops++;
6315 } else {
6316 data.value += (data.velocity ?? 0) * delta.factor;
6317 }
6318 break;
6319 case "decreasing":
6320 if (data.value <= minValue) {
6321 data.status = "increasing";
6322 if (!data.loops) {
6323 data.loops = 0;
6324 }
6325 data.loops++;
6326 } else {
6327 data.value -= (data.velocity ?? 0) * delta.factor;
6328 }
6329 break;
6330 }
6331 if (data.velocity && data.decay !== 1) {
6332 data.velocity *= decay;
6333 }
6334 checkDestroy(particle, data.value, minValue, maxValue);
6335 if (!particle.destroyed) {
6336 data.value = clamp(data.value, minValue, maxValue);
6337 }
6338}
6339;// CONCATENATED MODULE: ../../updaters/opacity/dist/esm/OpacityUpdater.js
6340
6341
6342class OpacityUpdater {
6343 constructor(container) {
6344 this.container = container;
6345 }
6346 init(particle) {
6347 const opacityOptions = particle.options.opacity;
6348 particle.opacity = initParticleNumericAnimationValue(opacityOptions, 1);
6349 const opacityAnimation = opacityOptions.animation;
6350 if (opacityAnimation.enable) {
6351 particle.opacity.velocity = getRangeValue(opacityAnimation.speed) / 100 * this.container.retina.reduceFactor;
6352 if (!opacityAnimation.sync) {
6353 particle.opacity.velocity *= getRandom();
6354 }
6355 }
6356 }
6357 isEnabled(particle) {
6358 return !particle.destroyed && !particle.spawning && !!particle.opacity && particle.opacity.enable && ((particle.opacity.maxLoops ?? 0) <= 0 || (particle.opacity.maxLoops ?? 0) > 0 && (particle.opacity.loops ?? 0) < (particle.opacity.maxLoops ?? 0));
6359 }
6360 reset(particle) {
6361 if (particle.opacity) {
6362 particle.opacity.time = 0;
6363 particle.opacity.loops = 0;
6364 }
6365 }
6366 update(particle, delta) {
6367 if (!this.isEnabled(particle)) {
6368 return;
6369 }
6370 updateOpacity(particle, delta);
6371 }
6372}
6373;// CONCATENATED MODULE: ../../updaters/opacity/dist/esm/index.js
6374
6375async function loadOpacityUpdater(engine, refresh = true) {
6376 await engine.addParticleUpdater("opacity", container => new OpacityUpdater(container), refresh);
6377}
6378;// CONCATENATED MODULE: ../../updaters/outModes/dist/esm/Utils.js
6379
6380function bounceHorizontal(data) {
6381 if (data.outMode !== "bounce" && data.outMode !== "bounce-horizontal" && data.outMode !== "bounceHorizontal" && data.outMode !== "split" || data.direction !== "left" && data.direction !== "right") {
6382 return;
6383 }
6384 if (data.bounds.right < 0 && data.direction === "left") {
6385 data.particle.position.x = data.size + data.offset.x;
6386 } else if (data.bounds.left > data.canvasSize.width && data.direction === "right") {
6387 data.particle.position.x = data.canvasSize.width - data.size - data.offset.x;
6388 }
6389 const velocity = data.particle.velocity.x;
6390 let bounced = false;
6391 if (data.direction === "right" && data.bounds.right >= data.canvasSize.width && velocity > 0 || data.direction === "left" && data.bounds.left <= 0 && velocity < 0) {
6392 const newVelocity = getValue(data.particle.options.bounce.horizontal);
6393 data.particle.velocity.x *= -newVelocity;
6394 bounced = true;
6395 }
6396 if (!bounced) {
6397 return;
6398 }
6399 const minPos = data.offset.x + data.size;
6400 if (data.bounds.right >= data.canvasSize.width && data.direction === "right") {
6401 data.particle.position.x = data.canvasSize.width - minPos;
6402 } else if (data.bounds.left <= 0 && data.direction === "left") {
6403 data.particle.position.x = minPos;
6404 }
6405 if (data.outMode === "split") {
6406 data.particle.destroy();
6407 }
6408}
6409function bounceVertical(data) {
6410 if (data.outMode !== "bounce" && data.outMode !== "bounce-vertical" && data.outMode !== "bounceVertical" && data.outMode !== "split" || data.direction !== "bottom" && data.direction !== "top") {
6411 return;
6412 }
6413 if (data.bounds.bottom < 0 && data.direction === "top") {
6414 data.particle.position.y = data.size + data.offset.y;
6415 } else if (data.bounds.top > data.canvasSize.height && data.direction === "bottom") {
6416 data.particle.position.y = data.canvasSize.height - data.size - data.offset.y;
6417 }
6418 const velocity = data.particle.velocity.y;
6419 let bounced = false;
6420 if (data.direction === "bottom" && data.bounds.bottom >= data.canvasSize.height && velocity > 0 || data.direction === "top" && data.bounds.top <= 0 && velocity < 0) {
6421 const newVelocity = getValue(data.particle.options.bounce.vertical);
6422 data.particle.velocity.y *= -newVelocity;
6423 bounced = true;
6424 }
6425 if (!bounced) {
6426 return;
6427 }
6428 const minPos = data.offset.y + data.size;
6429 if (data.bounds.bottom >= data.canvasSize.height && data.direction === "bottom") {
6430 data.particle.position.y = data.canvasSize.height - minPos;
6431 } else if (data.bounds.top <= 0 && data.direction === "top") {
6432 data.particle.position.y = minPos;
6433 }
6434 if (data.outMode === "split") {
6435 data.particle.destroy();
6436 }
6437}
6438;// CONCATENATED MODULE: ../../updaters/outModes/dist/esm/BounceOutMode.js
6439
6440
6441class BounceOutMode {
6442 constructor(container) {
6443 this.container = container;
6444 this.modes = ["bounce", "bounce-vertical", "bounce-horizontal", "bounceVertical", "bounceHorizontal", "split"];
6445 }
6446 update(particle, direction, delta, outMode) {
6447 if (!this.modes.includes(outMode)) {
6448 return;
6449 }
6450 const container = this.container;
6451 let handled = false;
6452 for (const [, plugin] of container.plugins) {
6453 if (plugin.particleBounce !== undefined) {
6454 handled = plugin.particleBounce(particle, delta, direction);
6455 }
6456 if (handled) {
6457 break;
6458 }
6459 }
6460 if (handled) {
6461 return;
6462 }
6463 const pos = particle.getPosition(),
6464 offset = particle.offset,
6465 size = particle.getRadius(),
6466 bounds = calculateBounds(pos, size),
6467 canvasSize = container.canvas.size;
6468 bounceHorizontal({
6469 particle,
6470 outMode,
6471 direction,
6472 bounds,
6473 canvasSize,
6474 offset,
6475 size
6476 });
6477 bounceVertical({
6478 particle,
6479 outMode,
6480 direction,
6481 bounds,
6482 canvasSize,
6483 offset,
6484 size
6485 });
6486 }
6487}
6488;// CONCATENATED MODULE: ../../updaters/outModes/dist/esm/DestroyOutMode.js
6489
6490class DestroyOutMode {
6491 constructor(container) {
6492 this.container = container;
6493 this.modes = ["destroy"];
6494 }
6495 update(particle, direction, _delta, outMode) {
6496 if (!this.modes.includes(outMode)) {
6497 return;
6498 }
6499 const container = this.container;
6500 switch (particle.outType) {
6501 case "normal":
6502 case "outside":
6503 if (isPointInside(particle.position, container.canvas.size, Vector.origin, particle.getRadius(), direction)) {
6504 return;
6505 }
6506 break;
6507 case "inside":
6508 {
6509 const {
6510 dx,
6511 dy
6512 } = getDistances(particle.position, particle.moveCenter);
6513 const {
6514 x: vx,
6515 y: vy
6516 } = particle.velocity;
6517 if (vx < 0 && dx > particle.moveCenter.radius || vy < 0 && dy > particle.moveCenter.radius || vx >= 0 && dx < -particle.moveCenter.radius || vy >= 0 && dy < -particle.moveCenter.radius) {
6518 return;
6519 }
6520 break;
6521 }
6522 }
6523 container.particles.remove(particle, undefined, true);
6524 }
6525}
6526;// CONCATENATED MODULE: ../../updaters/outModes/dist/esm/NoneOutMode.js
6527
6528class NoneOutMode {
6529 constructor(container) {
6530 this.container = container;
6531 this.modes = ["none"];
6532 }
6533 update(particle, direction, delta, outMode) {
6534 if (!this.modes.includes(outMode)) {
6535 return;
6536 }
6537 if (particle.options.move.distance.horizontal && (direction === "left" || direction === "right") || particle.options.move.distance.vertical && (direction === "top" || direction === "bottom")) {
6538 return;
6539 }
6540 const gravityOptions = particle.options.move.gravity,
6541 container = this.container;
6542 const canvasSize = container.canvas.size;
6543 const pRadius = particle.getRadius();
6544 if (!gravityOptions.enable) {
6545 if (particle.velocity.y > 0 && particle.position.y <= canvasSize.height + pRadius || particle.velocity.y < 0 && particle.position.y >= -pRadius || particle.velocity.x > 0 && particle.position.x <= canvasSize.width + pRadius || particle.velocity.x < 0 && particle.position.x >= -pRadius) {
6546 return;
6547 }
6548 if (!isPointInside(particle.position, container.canvas.size, Vector.origin, pRadius, direction)) {
6549 container.particles.remove(particle);
6550 }
6551 } else {
6552 const position = particle.position;
6553 if (!gravityOptions.inverse && position.y > canvasSize.height + pRadius && direction === "bottom" || gravityOptions.inverse && position.y < -pRadius && direction === "top") {
6554 container.particles.remove(particle);
6555 }
6556 }
6557 }
6558}
6559;// CONCATENATED MODULE: ../../updaters/outModes/dist/esm/OutOutMode.js
6560
6561class OutOutMode {
6562 constructor(container) {
6563 this.container = container;
6564 this.modes = ["out"];
6565 }
6566 update(particle, direction, delta, outMode) {
6567 if (!this.modes.includes(outMode)) {
6568 return;
6569 }
6570 const container = this.container;
6571 switch (particle.outType) {
6572 case "inside":
6573 {
6574 const {
6575 x: vx,
6576 y: vy
6577 } = particle.velocity;
6578 const circVec = Vector.origin;
6579 circVec.length = particle.moveCenter.radius;
6580 circVec.angle = particle.velocity.angle + Math.PI;
6581 circVec.addTo(Vector.create(particle.moveCenter));
6582 const {
6583 dx,
6584 dy
6585 } = getDistances(particle.position, circVec);
6586 if (vx <= 0 && dx >= 0 || vy <= 0 && dy >= 0 || vx >= 0 && dx <= 0 || vy >= 0 && dy <= 0) {
6587 return;
6588 }
6589 particle.position.x = Math.floor(randomInRange({
6590 min: 0,
6591 max: container.canvas.size.width
6592 }));
6593 particle.position.y = Math.floor(randomInRange({
6594 min: 0,
6595 max: container.canvas.size.height
6596 }));
6597 const {
6598 dx: newDx,
6599 dy: newDy
6600 } = getDistances(particle.position, particle.moveCenter);
6601 particle.direction = Math.atan2(-newDy, -newDx);
6602 particle.velocity.angle = particle.direction;
6603 break;
6604 }
6605 default:
6606 {
6607 if (isPointInside(particle.position, container.canvas.size, Vector.origin, particle.getRadius(), direction)) {
6608 return;
6609 }
6610 switch (particle.outType) {
6611 case "outside":
6612 {
6613 particle.position.x = Math.floor(randomInRange({
6614 min: -particle.moveCenter.radius,
6615 max: particle.moveCenter.radius
6616 })) + particle.moveCenter.x;
6617 particle.position.y = Math.floor(randomInRange({
6618 min: -particle.moveCenter.radius,
6619 max: particle.moveCenter.radius
6620 })) + particle.moveCenter.y;
6621 const {
6622 dx,
6623 dy
6624 } = getDistances(particle.position, particle.moveCenter);
6625 if (particle.moveCenter.radius) {
6626 particle.direction = Math.atan2(dy, dx);
6627 particle.velocity.angle = particle.direction;
6628 }
6629 break;
6630 }
6631 case "normal":
6632 {
6633 const wrap = particle.options.move.warp,
6634 canvasSize = container.canvas.size,
6635 newPos = {
6636 bottom: canvasSize.height + particle.getRadius() + particle.offset.y,
6637 left: -particle.getRadius() - particle.offset.x,
6638 right: canvasSize.width + particle.getRadius() + particle.offset.x,
6639 top: -particle.getRadius() - particle.offset.y
6640 },
6641 sizeValue = particle.getRadius(),
6642 nextBounds = calculateBounds(particle.position, sizeValue);
6643 if (direction === "right" && nextBounds.left > canvasSize.width + particle.offset.x) {
6644 particle.position.x = newPos.left;
6645 particle.initialPosition.x = particle.position.x;
6646 if (!wrap) {
6647 particle.position.y = getRandom() * canvasSize.height;
6648 particle.initialPosition.y = particle.position.y;
6649 }
6650 } else if (direction === "left" && nextBounds.right < -particle.offset.x) {
6651 particle.position.x = newPos.right;
6652 particle.initialPosition.x = particle.position.x;
6653 if (!wrap) {
6654 particle.position.y = getRandom() * canvasSize.height;
6655 particle.initialPosition.y = particle.position.y;
6656 }
6657 }
6658 if (direction === "bottom" && nextBounds.top > canvasSize.height + particle.offset.y) {
6659 if (!wrap) {
6660 particle.position.x = getRandom() * canvasSize.width;
6661 particle.initialPosition.x = particle.position.x;
6662 }
6663 particle.position.y = newPos.top;
6664 particle.initialPosition.y = particle.position.y;
6665 } else if (direction === "top" && nextBounds.bottom < -particle.offset.y) {
6666 if (!wrap) {
6667 particle.position.x = getRandom() * canvasSize.width;
6668 particle.initialPosition.x = particle.position.x;
6669 }
6670 particle.position.y = newPos.bottom;
6671 particle.initialPosition.y = particle.position.y;
6672 }
6673 break;
6674 }
6675 }
6676 break;
6677 }
6678 }
6679 }
6680}
6681;// CONCATENATED MODULE: ../../updaters/outModes/dist/esm/OutOfCanvasUpdater.js
6682
6683
6684
6685
6686class OutOfCanvasUpdater {
6687 constructor(container) {
6688 this.container = container;
6689 this._updateOutMode = (particle, delta, outMode, direction) => {
6690 for (const updater of this.updaters) {
6691 updater.update(particle, direction, delta, outMode);
6692 }
6693 };
6694 this.updaters = [new BounceOutMode(container), new DestroyOutMode(container), new OutOutMode(container), new NoneOutMode(container)];
6695 }
6696 init() {}
6697 isEnabled(particle) {
6698 return !particle.destroyed && !particle.spawning;
6699 }
6700 update(particle, delta) {
6701 const outModes = particle.options.move.outModes;
6702 this._updateOutMode(particle, delta, outModes.bottom ?? outModes.default, "bottom");
6703 this._updateOutMode(particle, delta, outModes.left ?? outModes.default, "left");
6704 this._updateOutMode(particle, delta, outModes.right ?? outModes.default, "right");
6705 this._updateOutMode(particle, delta, outModes.top ?? outModes.default, "top");
6706 }
6707}
6708;// CONCATENATED MODULE: ../../updaters/outModes/dist/esm/index.js
6709
6710async function loadOutModesUpdater(engine, refresh = true) {
6711 await engine.addParticleUpdater("outModes", container => new OutOfCanvasUpdater(container), refresh);
6712}
6713;// CONCATENATED MODULE: ../../updaters/size/dist/esm/Utils.js
6714
6715function Utils_checkDestroy(particle, value, minValue, maxValue) {
6716 switch (particle.options.size.animation.destroy) {
6717 case "max":
6718 if (value >= maxValue) {
6719 particle.destroy();
6720 }
6721 break;
6722 case "min":
6723 if (value <= minValue) {
6724 particle.destroy();
6725 }
6726 break;
6727 }
6728}
6729function updateSize(particle, delta) {
6730 const data = particle.size;
6731 if (particle.destroyed || !data || !data.enable || (data.maxLoops ?? 0) > 0 && (data.loops ?? 0) > (data.maxLoops ?? 0)) {
6732 return;
6733 }
6734 const sizeVelocity = (data.velocity ?? 0) * delta.factor,
6735 minValue = data.min,
6736 maxValue = data.max,
6737 decay = data.decay ?? 1;
6738 if (!data.time) {
6739 data.time = 0;
6740 }
6741 if ((data.delayTime ?? 0) > 0 && data.time < (data.delayTime ?? 0)) {
6742 data.time += delta.value;
6743 }
6744 if ((data.delayTime ?? 0) > 0 && data.time < (data.delayTime ?? 0)) {
6745 return;
6746 }
6747 switch (data.status) {
6748 case "increasing":
6749 if (data.value >= maxValue) {
6750 data.status = "decreasing";
6751 if (!data.loops) {
6752 data.loops = 0;
6753 }
6754 data.loops++;
6755 } else {
6756 data.value += sizeVelocity;
6757 }
6758 break;
6759 case "decreasing":
6760 if (data.value <= minValue) {
6761 data.status = "increasing";
6762 if (!data.loops) {
6763 data.loops = 0;
6764 }
6765 data.loops++;
6766 } else {
6767 data.value -= sizeVelocity;
6768 }
6769 }
6770 if (data.velocity && decay !== 1) {
6771 data.velocity *= decay;
6772 }
6773 Utils_checkDestroy(particle, data.value, minValue, maxValue);
6774 if (!particle.destroyed) {
6775 data.value = clamp(data.value, minValue, maxValue);
6776 }
6777}
6778;// CONCATENATED MODULE: ../../updaters/size/dist/esm/SizeUpdater.js
6779
6780
6781class SizeUpdater {
6782 init(particle) {
6783 const container = particle.container,
6784 sizeOptions = particle.options.size,
6785 sizeAnimation = sizeOptions.animation;
6786 if (sizeAnimation.enable) {
6787 particle.size.velocity = (particle.retina.sizeAnimationSpeed ?? container.retina.sizeAnimationSpeed) / 100 * container.retina.reduceFactor;
6788 if (!sizeAnimation.sync) {
6789 particle.size.velocity *= getRandom();
6790 }
6791 }
6792 }
6793 isEnabled(particle) {
6794 return !particle.destroyed && !particle.spawning && particle.size.enable && ((particle.size.maxLoops ?? 0) <= 0 || (particle.size.maxLoops ?? 0) > 0 && (particle.size.loops ?? 0) < (particle.size.maxLoops ?? 0));
6795 }
6796 reset(particle) {
6797 particle.size.loops = 0;
6798 }
6799 update(particle, delta) {
6800 if (!this.isEnabled(particle)) {
6801 return;
6802 }
6803 updateSize(particle, delta);
6804 }
6805}
6806;// CONCATENATED MODULE: ../../updaters/size/dist/esm/index.js
6807
6808async function loadSizeUpdater(engine, refresh = true) {
6809 await engine.addParticleUpdater("size", () => new SizeUpdater(), refresh);
6810}
6811;// CONCATENATED MODULE: ../basic/dist/esm/index.js
6812
6813
6814
6815
6816
6817
6818async function loadBasic(engine, refresh = true) {
6819 await loadBaseMover(engine, false);
6820 await loadCircleShape(engine, false);
6821 await loadColorUpdater(engine, false);
6822 await loadOpacityUpdater(engine, false);
6823 await loadOutModesUpdater(engine, false);
6824 await loadSizeUpdater(engine, false);
6825 await engine.refresh(refresh);
6826}
6827;// CONCATENATED MODULE: ../../plugins/easings/quad/dist/esm/index.js
6828
6829async function loadEasingQuadPlugin() {
6830 addEasing("ease-in-quad", value => value ** 2);
6831 addEasing("ease-out-quad", value => 1 - (1 - value) ** 2);
6832 addEasing("ease-in-out-quad", value => value < 0.5 ? 2 * value ** 2 : 1 - (-2 * value + 2) ** 2 / 2);
6833}
6834;// CONCATENATED MODULE: ../../interactions/external/attract/dist/esm/Options/Classes/Attract.js
6835class Attract {
6836 constructor() {
6837 this.distance = 200;
6838 this.duration = 0.4;
6839 this.easing = "ease-out-quad";
6840 this.factor = 1;
6841 this.maxSpeed = 50;
6842 this.speed = 1;
6843 }
6844 load(data) {
6845 if (!data) {
6846 return;
6847 }
6848 if (data.distance !== undefined) {
6849 this.distance = data.distance;
6850 }
6851 if (data.duration !== undefined) {
6852 this.duration = data.duration;
6853 }
6854 if (data.easing !== undefined) {
6855 this.easing = data.easing;
6856 }
6857 if (data.factor !== undefined) {
6858 this.factor = data.factor;
6859 }
6860 if (data.maxSpeed !== undefined) {
6861 this.maxSpeed = data.maxSpeed;
6862 }
6863 if (data.speed !== undefined) {
6864 this.speed = data.speed;
6865 }
6866 }
6867}
6868;// CONCATENATED MODULE: ../../interactions/external/attract/dist/esm/Attractor.js
6869
6870
6871class Attractor extends ExternalInteractorBase {
6872 constructor(engine, container) {
6873 super(container);
6874 this._clickAttract = () => {
6875 const container = this.container;
6876 if (!container.attract) {
6877 container.attract = {
6878 particles: []
6879 };
6880 }
6881 const {
6882 attract
6883 } = container;
6884 if (!attract.finish) {
6885 if (!attract.count) {
6886 attract.count = 0;
6887 }
6888 attract.count++;
6889 if (attract.count === container.particles.count) {
6890 attract.finish = true;
6891 }
6892 }
6893 if (attract.clicking) {
6894 const mousePos = container.interactivity.mouse.clickPosition,
6895 attractRadius = container.retina.attractModeDistance;
6896 if (!attractRadius || attractRadius < 0 || !mousePos) {
6897 return;
6898 }
6899 this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
6900 } else if (attract.clicking === false) {
6901 attract.particles = [];
6902 }
6903 return;
6904 };
6905 this._hoverAttract = () => {
6906 const container = this.container,
6907 mousePos = container.interactivity.mouse.position,
6908 attractRadius = container.retina.attractModeDistance;
6909 if (!attractRadius || attractRadius < 0 || !mousePos) {
6910 return;
6911 }
6912 this._processAttract(mousePos, attractRadius, new Circle(mousePos.x, mousePos.y, attractRadius));
6913 };
6914 this._processAttract = (position, attractRadius, area) => {
6915 const container = this.container,
6916 attractOptions = container.actualOptions.interactivity.modes.attract;
6917 if (!attractOptions) {
6918 return;
6919 }
6920 const query = container.particles.quadTree.query(area, p => this.isEnabled(p));
6921 for (const particle of query) {
6922 const {
6923 dx,
6924 dy,
6925 distance
6926 } = getDistances(particle.position, position);
6927 const velocity = attractOptions.speed * attractOptions.factor;
6928 const attractFactor = clamp(getEasing(attractOptions.easing)(1 - distance / attractRadius) * velocity, 0, attractOptions.maxSpeed);
6929 const normVec = Vector.create(distance === 0 ? velocity : dx / distance * attractFactor, distance === 0 ? velocity : dy / distance * attractFactor);
6930 particle.position.subFrom(normVec);
6931 }
6932 };
6933 this._engine = engine;
6934 if (!container.attract) {
6935 container.attract = {
6936 particles: []
6937 };
6938 }
6939 this.handleClickMode = mode => {
6940 const options = this.container.actualOptions,
6941 attract = options.interactivity.modes.attract;
6942 if (!attract || mode !== "attract") {
6943 return;
6944 }
6945 if (!container.attract) {
6946 container.attract = {
6947 particles: []
6948 };
6949 }
6950 container.attract.clicking = true;
6951 container.attract.count = 0;
6952 for (const particle of container.attract.particles) {
6953 if (!this.isEnabled(particle)) {
6954 continue;
6955 }
6956 particle.velocity.setTo(particle.initialVelocity);
6957 }
6958 container.attract.particles = [];
6959 container.attract.finish = false;
6960 setTimeout(() => {
6961 if (container.destroyed) {
6962 return;
6963 }
6964 if (!container.attract) {
6965 container.attract = {
6966 particles: []
6967 };
6968 }
6969 container.attract.clicking = false;
6970 }, attract.duration * 1000);
6971 };
6972 }
6973 clear() {}
6974 init() {
6975 const container = this.container,
6976 attract = container.actualOptions.interactivity.modes.attract;
6977 if (!attract) {
6978 return;
6979 }
6980 container.retina.attractModeDistance = attract.distance * container.retina.pixelRatio;
6981 }
6982 async interact() {
6983 const container = this.container,
6984 options = container.actualOptions,
6985 mouseMoveStatus = container.interactivity.status === mouseMoveEvent,
6986 events = options.interactivity.events,
6987 hoverEnabled = events.onHover.enable,
6988 hoverMode = events.onHover.mode,
6989 clickEnabled = events.onClick.enable,
6990 clickMode = events.onClick.mode;
6991 if (mouseMoveStatus && hoverEnabled && isInArray("attract", hoverMode)) {
6992 this._hoverAttract();
6993 } else if (clickEnabled && isInArray("attract", clickMode)) {
6994 this._clickAttract();
6995 }
6996 }
6997 isEnabled(particle) {
6998 const container = this.container,
6999 options = container.actualOptions,
7000 mouse = container.interactivity.mouse,
7001 events = (particle?.interactivity ?? options.interactivity).events;
7002 if ((!mouse.position || !events.onHover.enable) && (!mouse.clickPosition || !events.onClick.enable)) {
7003 return false;
7004 }
7005 const hoverMode = events.onHover.mode,
7006 clickMode = events.onClick.mode;
7007 return isInArray("attract", hoverMode) || isInArray("attract", clickMode);
7008 }
7009 loadModeOptions(options, ...sources) {
7010 if (!options.attract) {
7011 options.attract = new Attract();
7012 }
7013 for (const source of sources) {
7014 options.attract.load(source?.attract);
7015 }
7016 }
7017 reset() {}
7018}
7019;// CONCATENATED MODULE: ../../interactions/external/attract/dist/esm/index.js
7020
7021async function loadExternalAttractInteraction(engine, refresh = true) {
7022 await engine.addInteractor("externalAttract", container => new Attractor(engine, container), refresh);
7023}
7024
7025
7026;// CONCATENATED MODULE: ../../interactions/external/bounce/dist/esm/Options/Classes/Bounce.js
7027class Bounce {
7028 constructor() {
7029 this.distance = 200;
7030 }
7031 load(data) {
7032 if (!data) {
7033 return;
7034 }
7035 if (data.distance !== undefined) {
7036 this.distance = data.distance;
7037 }
7038 }
7039}
7040;// CONCATENATED MODULE: ../../interactions/external/bounce/dist/esm/Bouncer.js
7041
7042
7043class Bouncer extends ExternalInteractorBase {
7044 constructor(container) {
7045 super(container);
7046 this._processBounce = (position, radius, area) => {
7047 const query = this.container.particles.quadTree.query(area, p => this.isEnabled(p));
7048 for (const particle of query) {
7049 if (area instanceof Circle) {
7050 circleBounce(circleBounceDataFromParticle(particle), {
7051 position,
7052 radius,
7053 mass: radius ** 2 * Math.PI / 2,
7054 velocity: Vector.origin,
7055 factor: Vector.origin
7056 });
7057 } else if (area instanceof Rectangle) {
7058 rectBounce(particle, calculateBounds(position, radius));
7059 }
7060 }
7061 };
7062 this._processMouseBounce = () => {
7063 const container = this.container,
7064 pxRatio = container.retina.pixelRatio,
7065 tolerance = 10 * pxRatio,
7066 mousePos = container.interactivity.mouse.position,
7067 radius = container.retina.bounceModeDistance;
7068 if (!radius || radius < 0 || !mousePos) {
7069 return;
7070 }
7071 this._processBounce(mousePos, radius, new Circle(mousePos.x, mousePos.y, radius + tolerance));
7072 };
7073 this._singleSelectorBounce = (selector, div) => {
7074 const container = this.container,
7075 query = document.querySelectorAll(selector);
7076 if (!query.length) {
7077 return;
7078 }
7079 query.forEach(item => {
7080 const elem = item,
7081 pxRatio = container.retina.pixelRatio,
7082 pos = {
7083 x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
7084 y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio
7085 },
7086 radius = elem.offsetWidth / 2 * pxRatio,
7087 tolerance = 10 * pxRatio,
7088 area = div.type === "circle" ? new Circle(pos.x, pos.y, radius + tolerance) : new Rectangle(elem.offsetLeft * pxRatio - tolerance, elem.offsetTop * pxRatio - tolerance, elem.offsetWidth * pxRatio + tolerance * 2, elem.offsetHeight * pxRatio + tolerance * 2);
7089 this._processBounce(pos, radius, area);
7090 });
7091 };
7092 }
7093 clear() {}
7094 init() {
7095 const container = this.container,
7096 bounce = container.actualOptions.interactivity.modes.bounce;
7097 if (!bounce) {
7098 return;
7099 }
7100 container.retina.bounceModeDistance = bounce.distance * container.retina.pixelRatio;
7101 }
7102 async interact() {
7103 const container = this.container,
7104 options = container.actualOptions,
7105 events = options.interactivity.events,
7106 mouseMoveStatus = container.interactivity.status === mouseMoveEvent,
7107 hoverEnabled = events.onHover.enable,
7108 hoverMode = events.onHover.mode,
7109 divs = events.onDiv;
7110 if (mouseMoveStatus && hoverEnabled && isInArray("bounce", hoverMode)) {
7111 this._processMouseBounce();
7112 } else {
7113 divModeExecute("bounce", divs, (selector, div) => this._singleSelectorBounce(selector, div));
7114 }
7115 }
7116 isEnabled(particle) {
7117 const container = this.container,
7118 options = container.actualOptions,
7119 mouse = container.interactivity.mouse,
7120 events = (particle?.interactivity ?? options.interactivity).events,
7121 divs = events.onDiv;
7122 return mouse.position && events.onHover.enable && isInArray("bounce", events.onHover.mode) || isDivModeEnabled("bounce", divs);
7123 }
7124 loadModeOptions(options, ...sources) {
7125 if (!options.bounce) {
7126 options.bounce = new Bounce();
7127 }
7128 for (const source of sources) {
7129 options.bounce.load(source?.bounce);
7130 }
7131 }
7132 reset() {}
7133}
7134;// CONCATENATED MODULE: ../../interactions/external/bounce/dist/esm/index.js
7135
7136async function loadExternalBounceInteraction(engine, refresh = true) {
7137 await engine.addInteractor("externalBounce", container => new Bouncer(container), refresh);
7138}
7139
7140
7141;// CONCATENATED MODULE: ../../interactions/external/bubble/dist/esm/Options/Classes/BubbleBase.js
7142
7143class BubbleBase {
7144 constructor() {
7145 this.distance = 200;
7146 this.duration = 0.4;
7147 this.mix = false;
7148 }
7149 load(data) {
7150 if (!data) {
7151 return;
7152 }
7153 if (data.distance !== undefined) {
7154 this.distance = data.distance;
7155 }
7156 if (data.duration !== undefined) {
7157 this.duration = data.duration;
7158 }
7159 if (data.mix !== undefined) {
7160 this.mix = data.mix;
7161 }
7162 if (data.opacity !== undefined) {
7163 this.opacity = data.opacity;
7164 }
7165 if (data.color !== undefined) {
7166 const sourceColor = isArray(this.color) ? undefined : this.color;
7167 this.color = executeOnSingleOrMultiple(data.color, color => {
7168 return OptionsColor.create(sourceColor, color);
7169 });
7170 }
7171 if (data.size !== undefined) {
7172 this.size = data.size;
7173 }
7174 }
7175}
7176;// CONCATENATED MODULE: ../../interactions/external/bubble/dist/esm/Options/Classes/BubbleDiv.js
7177
7178
7179class BubbleDiv extends BubbleBase {
7180 constructor() {
7181 super();
7182 this.selectors = [];
7183 }
7184 get ids() {
7185 return executeOnSingleOrMultiple(this.selectors, t => t.replace("#", ""));
7186 }
7187 set ids(value) {
7188 this.selectors = executeOnSingleOrMultiple(value, t => `#${t}`);
7189 }
7190 load(data) {
7191 super.load(data);
7192 if (!data) {
7193 return;
7194 }
7195 if (data.ids !== undefined) {
7196 this.ids = data.ids;
7197 }
7198 if (data.selectors !== undefined) {
7199 this.selectors = data.selectors;
7200 }
7201 }
7202}
7203;// CONCATENATED MODULE: ../../interactions/external/bubble/dist/esm/Options/Classes/Bubble.js
7204
7205
7206
7207class Bubble extends BubbleBase {
7208 load(data) {
7209 super.load(data);
7210 if (!data) {
7211 return;
7212 }
7213 this.divs = executeOnSingleOrMultiple(data.divs, div => {
7214 const tmp = new BubbleDiv();
7215 tmp.load(div);
7216 return tmp;
7217 });
7218 }
7219}
7220;// CONCATENATED MODULE: ../../interactions/external/bubble/dist/esm/Utils.js
7221
7222function calculateBubbleValue(particleValue, modeValue, optionsValue, ratio) {
7223 if (modeValue >= optionsValue) {
7224 const value = particleValue + (modeValue - optionsValue) * ratio;
7225 return clamp(value, particleValue, modeValue);
7226 } else if (modeValue < optionsValue) {
7227 const value = particleValue - (optionsValue - modeValue) * ratio;
7228 return clamp(value, modeValue, particleValue);
7229 }
7230}
7231;// CONCATENATED MODULE: ../../interactions/external/bubble/dist/esm/Bubbler.js
7232
7233
7234
7235class Bubbler extends ExternalInteractorBase {
7236 constructor(container) {
7237 super(container);
7238 this._clickBubble = () => {
7239 const container = this.container,
7240 options = container.actualOptions,
7241 mouseClickPos = container.interactivity.mouse.clickPosition,
7242 bubbleOptions = options.interactivity.modes.bubble;
7243 if (!bubbleOptions || !mouseClickPos) {
7244 return;
7245 }
7246 if (!container.bubble) {
7247 container.bubble = {};
7248 }
7249 const distance = container.retina.bubbleModeDistance;
7250 if (!distance || distance < 0) {
7251 return;
7252 }
7253 const query = container.particles.quadTree.queryCircle(mouseClickPos, distance, p => this.isEnabled(p)),
7254 {
7255 bubble
7256 } = container;
7257 for (const particle of query) {
7258 if (!bubble.clicking) {
7259 continue;
7260 }
7261 particle.bubble.inRange = !bubble.durationEnd;
7262 const pos = particle.getPosition(),
7263 distMouse = getDistance(pos, mouseClickPos),
7264 timeSpent = (new Date().getTime() - (container.interactivity.mouse.clickTime || 0)) / 1000;
7265 if (timeSpent > bubbleOptions.duration) {
7266 bubble.durationEnd = true;
7267 }
7268 if (timeSpent > bubbleOptions.duration * 2) {
7269 bubble.clicking = false;
7270 bubble.durationEnd = false;
7271 }
7272 const sizeData = {
7273 bubbleObj: {
7274 optValue: container.retina.bubbleModeSize,
7275 value: particle.bubble.radius
7276 },
7277 particlesObj: {
7278 optValue: getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
7279 value: particle.size.value
7280 },
7281 type: "size"
7282 };
7283 this._process(particle, distMouse, timeSpent, sizeData);
7284 const opacityData = {
7285 bubbleObj: {
7286 optValue: bubbleOptions.opacity,
7287 value: particle.bubble.opacity
7288 },
7289 particlesObj: {
7290 optValue: getRangeMax(particle.options.opacity.value),
7291 value: particle.opacity?.value ?? 1
7292 },
7293 type: "opacity"
7294 };
7295 this._process(particle, distMouse, timeSpent, opacityData);
7296 if (!bubble.durationEnd && distMouse <= distance) {
7297 this._hoverBubbleColor(particle, distMouse);
7298 } else {
7299 delete particle.bubble.color;
7300 }
7301 }
7302 };
7303 this._hoverBubble = () => {
7304 const container = this.container,
7305 mousePos = container.interactivity.mouse.position,
7306 distance = container.retina.bubbleModeDistance;
7307 if (!distance || distance < 0 || mousePos === undefined) {
7308 return;
7309 }
7310 const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
7311 for (const particle of query) {
7312 particle.bubble.inRange = true;
7313 const pos = particle.getPosition(),
7314 pointDistance = getDistance(pos, mousePos),
7315 ratio = 1 - pointDistance / distance;
7316 if (pointDistance <= distance) {
7317 if (ratio >= 0 && container.interactivity.status === mouseMoveEvent) {
7318 this._hoverBubbleSize(particle, ratio);
7319 this._hoverBubbleOpacity(particle, ratio);
7320 this._hoverBubbleColor(particle, ratio);
7321 }
7322 } else {
7323 this.reset(particle);
7324 }
7325 if (container.interactivity.status === mouseLeaveEvent) {
7326 this.reset(particle);
7327 }
7328 }
7329 };
7330 this._hoverBubbleColor = (particle, ratio, divBubble) => {
7331 const options = this.container.actualOptions,
7332 bubbleOptions = divBubble ?? options.interactivity.modes.bubble;
7333 if (!bubbleOptions) {
7334 return;
7335 }
7336 if (!particle.bubble.finalColor) {
7337 const modeColor = bubbleOptions.color;
7338 if (!modeColor) {
7339 return;
7340 }
7341 const bubbleColor = itemFromSingleOrMultiple(modeColor);
7342 particle.bubble.finalColor = rangeColorToHsl(bubbleColor);
7343 }
7344 if (!particle.bubble.finalColor) {
7345 return;
7346 }
7347 if (bubbleOptions.mix) {
7348 particle.bubble.color = undefined;
7349 const pColor = particle.getFillColor();
7350 particle.bubble.color = pColor ? rgbToHsl(colorMix(pColor, particle.bubble.finalColor, 1 - ratio, ratio)) : particle.bubble.finalColor;
7351 } else {
7352 particle.bubble.color = particle.bubble.finalColor;
7353 }
7354 };
7355 this._hoverBubbleOpacity = (particle, ratio, divBubble) => {
7356 const container = this.container,
7357 options = container.actualOptions,
7358 modeOpacity = divBubble?.opacity ?? options.interactivity.modes.bubble?.opacity;
7359 if (!modeOpacity) {
7360 return;
7361 }
7362 const optOpacity = particle.options.opacity.value,
7363 pOpacity = particle.opacity?.value ?? 1,
7364 opacity = calculateBubbleValue(pOpacity, modeOpacity, getRangeMax(optOpacity), ratio);
7365 if (opacity !== undefined) {
7366 particle.bubble.opacity = opacity;
7367 }
7368 };
7369 this._hoverBubbleSize = (particle, ratio, divBubble) => {
7370 const container = this.container,
7371 modeSize = divBubble?.size ? divBubble.size * container.retina.pixelRatio : container.retina.bubbleModeSize;
7372 if (modeSize === undefined) {
7373 return;
7374 }
7375 const optSize = getRangeMax(particle.options.size.value) * container.retina.pixelRatio,
7376 pSize = particle.size.value,
7377 size = calculateBubbleValue(pSize, modeSize, optSize, ratio);
7378 if (size !== undefined) {
7379 particle.bubble.radius = size;
7380 }
7381 };
7382 this._process = (particle, distMouse, timeSpent, data) => {
7383 const container = this.container,
7384 bubbleParam = data.bubbleObj.optValue,
7385 options = container.actualOptions,
7386 bubbleOptions = options.interactivity.modes.bubble;
7387 if (!bubbleOptions || bubbleParam === undefined) {
7388 return;
7389 }
7390 const bubbleDuration = bubbleOptions.duration,
7391 bubbleDistance = container.retina.bubbleModeDistance,
7392 particlesParam = data.particlesObj.optValue,
7393 pObjBubble = data.bubbleObj.value,
7394 pObj = data.particlesObj.value || 0,
7395 type = data.type;
7396 if (!bubbleDistance || bubbleDistance < 0 || bubbleParam === particlesParam) {
7397 return;
7398 }
7399 if (!container.bubble) {
7400 container.bubble = {};
7401 }
7402 if (container.bubble.durationEnd) {
7403 if (pObjBubble) {
7404 if (type === "size") {
7405 delete particle.bubble.radius;
7406 }
7407 if (type === "opacity") {
7408 delete particle.bubble.opacity;
7409 }
7410 }
7411 } else {
7412 if (distMouse <= bubbleDistance) {
7413 const obj = pObjBubble ?? pObj;
7414 if (obj !== bubbleParam) {
7415 const value = pObj - timeSpent * (pObj - bubbleParam) / bubbleDuration;
7416 if (type === "size") {
7417 particle.bubble.radius = value;
7418 }
7419 if (type === "opacity") {
7420 particle.bubble.opacity = value;
7421 }
7422 }
7423 } else {
7424 if (type === "size") {
7425 delete particle.bubble.radius;
7426 }
7427 if (type === "opacity") {
7428 delete particle.bubble.opacity;
7429 }
7430 }
7431 }
7432 };
7433 this._singleSelectorHover = (delta, selector, div) => {
7434 const container = this.container,
7435 selectors = document.querySelectorAll(selector),
7436 bubble = container.actualOptions.interactivity.modes.bubble;
7437 if (!bubble || !selectors.length) {
7438 return;
7439 }
7440 selectors.forEach(item => {
7441 const elem = item,
7442 pxRatio = container.retina.pixelRatio,
7443 pos = {
7444 x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
7445 y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio
7446 },
7447 repulseRadius = elem.offsetWidth / 2 * pxRatio,
7448 area = div.type === "circle" ? new Circle(pos.x, pos.y, repulseRadius) : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio),
7449 query = container.particles.quadTree.query(area, p => this.isEnabled(p));
7450 for (const particle of query) {
7451 if (!area.contains(particle.getPosition())) {
7452 continue;
7453 }
7454 particle.bubble.inRange = true;
7455 const divs = bubble.divs,
7456 divBubble = divMode(divs, elem);
7457 if (!particle.bubble.div || particle.bubble.div !== elem) {
7458 this.clear(particle, delta, true);
7459 particle.bubble.div = elem;
7460 }
7461 this._hoverBubbleSize(particle, 1, divBubble);
7462 this._hoverBubbleOpacity(particle, 1, divBubble);
7463 this._hoverBubbleColor(particle, 1, divBubble);
7464 }
7465 });
7466 };
7467 if (!container.bubble) {
7468 container.bubble = {};
7469 }
7470 this.handleClickMode = mode => {
7471 if (mode !== "bubble") {
7472 return;
7473 }
7474 if (!container.bubble) {
7475 container.bubble = {};
7476 }
7477 container.bubble.clicking = true;
7478 };
7479 }
7480 clear(particle, delta, force) {
7481 if (particle.bubble.inRange && !force) {
7482 return;
7483 }
7484 delete particle.bubble.div;
7485 delete particle.bubble.opacity;
7486 delete particle.bubble.radius;
7487 delete particle.bubble.color;
7488 }
7489 init() {
7490 const container = this.container,
7491 bubble = container.actualOptions.interactivity.modes.bubble;
7492 if (!bubble) {
7493 return;
7494 }
7495 container.retina.bubbleModeDistance = bubble.distance * container.retina.pixelRatio;
7496 if (bubble.size !== undefined) {
7497 container.retina.bubbleModeSize = bubble.size * container.retina.pixelRatio;
7498 }
7499 }
7500 async interact(delta) {
7501 const options = this.container.actualOptions,
7502 events = options.interactivity.events,
7503 onHover = events.onHover,
7504 onClick = events.onClick,
7505 hoverEnabled = onHover.enable,
7506 hoverMode = onHover.mode,
7507 clickEnabled = onClick.enable,
7508 clickMode = onClick.mode,
7509 divs = events.onDiv;
7510 if (hoverEnabled && isInArray("bubble", hoverMode)) {
7511 this._hoverBubble();
7512 } else if (clickEnabled && isInArray("bubble", clickMode)) {
7513 this._clickBubble();
7514 } else {
7515 divModeExecute("bubble", divs, (selector, div) => this._singleSelectorHover(delta, selector, div));
7516 }
7517 }
7518 isEnabled(particle) {
7519 const container = this.container,
7520 options = container.actualOptions,
7521 mouse = container.interactivity.mouse,
7522 events = (particle?.interactivity ?? options.interactivity).events,
7523 {
7524 onClick,
7525 onDiv,
7526 onHover
7527 } = events,
7528 divBubble = isDivModeEnabled("bubble", onDiv);
7529 if (!(divBubble || onHover.enable && mouse.position || onClick.enable && mouse.clickPosition)) {
7530 return false;
7531 }
7532 return isInArray("bubble", onHover.mode) || isInArray("bubble", onClick.mode) || divBubble;
7533 }
7534 loadModeOptions(options, ...sources) {
7535 if (!options.bubble) {
7536 options.bubble = new Bubble();
7537 }
7538 for (const source of sources) {
7539 options.bubble.load(source?.bubble);
7540 }
7541 }
7542 reset(particle) {
7543 particle.bubble.inRange = false;
7544 }
7545}
7546;// CONCATENATED MODULE: ../../interactions/external/bubble/dist/esm/index.js
7547
7548async function loadExternalBubbleInteraction(engine, refresh = true) {
7549 await engine.addInteractor("externalBubble", container => new Bubbler(container), refresh);
7550}
7551
7552
7553
7554
7555
7556
7557;// CONCATENATED MODULE: ../../interactions/external/connect/dist/esm/Options/Classes/ConnectLinks.js
7558class ConnectLinks {
7559 constructor() {
7560 this.opacity = 0.5;
7561 }
7562 load(data) {
7563 if (!data) {
7564 return;
7565 }
7566 if (data.opacity !== undefined) {
7567 this.opacity = data.opacity;
7568 }
7569 }
7570}
7571;// CONCATENATED MODULE: ../../interactions/external/connect/dist/esm/Options/Classes/Connect.js
7572
7573class Connect {
7574 constructor() {
7575 this.distance = 80;
7576 this.links = new ConnectLinks();
7577 this.radius = 60;
7578 }
7579 get lineLinked() {
7580 return this.links;
7581 }
7582 set lineLinked(value) {
7583 this.links = value;
7584 }
7585 get line_linked() {
7586 return this.links;
7587 }
7588 set line_linked(value) {
7589 this.links = value;
7590 }
7591 load(data) {
7592 if (!data) {
7593 return;
7594 }
7595 if (data.distance !== undefined) {
7596 this.distance = data.distance;
7597 }
7598 this.links.load(data.links ?? data.lineLinked ?? data.line_linked);
7599 if (data.radius !== undefined) {
7600 this.radius = data.radius;
7601 }
7602 }
7603}
7604;// CONCATENATED MODULE: ../../interactions/external/connect/dist/esm/Utils.js
7605
7606function gradient(context, p1, p2, opacity) {
7607 const gradStop = Math.floor(p2.getRadius() / p1.getRadius()),
7608 color1 = p1.getFillColor(),
7609 color2 = p2.getFillColor();
7610 if (!color1 || !color2) {
7611 return;
7612 }
7613 const sourcePos = p1.getPosition(),
7614 destPos = p2.getPosition(),
7615 midRgb = colorMix(color1, color2, p1.getRadius(), p2.getRadius()),
7616 grad = context.createLinearGradient(sourcePos.x, sourcePos.y, destPos.x, destPos.y);
7617 grad.addColorStop(0, getStyleFromHsl(color1, opacity));
7618 grad.addColorStop(gradStop > 1 ? 1 : gradStop, getStyleFromRgb(midRgb, opacity));
7619 grad.addColorStop(1, getStyleFromHsl(color2, opacity));
7620 return grad;
7621}
7622function drawConnectLine(context, width, lineStyle, begin, end) {
7623 drawLine(context, begin, end);
7624 context.lineWidth = width;
7625 context.strokeStyle = lineStyle;
7626 context.stroke();
7627}
7628function lineStyle(container, ctx, p1, p2) {
7629 const options = container.actualOptions,
7630 connectOptions = options.interactivity.modes.connect;
7631 if (!connectOptions) {
7632 return;
7633 }
7634 return gradient(ctx, p1, p2, connectOptions.links.opacity);
7635}
7636function drawConnection(container, p1, p2) {
7637 container.canvas.draw(ctx => {
7638 const ls = lineStyle(container, ctx, p1, p2);
7639 if (!ls) {
7640 return;
7641 }
7642 const pos1 = p1.getPosition(),
7643 pos2 = p2.getPosition();
7644 drawConnectLine(ctx, p1.retina.linksWidth ?? 0, ls, pos1, pos2);
7645 });
7646}
7647;// CONCATENATED MODULE: ../../interactions/external/connect/dist/esm/Connector.js
7648
7649
7650
7651class Connector extends ExternalInteractorBase {
7652 constructor(container) {
7653 super(container);
7654 }
7655 clear() {}
7656 init() {
7657 const container = this.container,
7658 connect = container.actualOptions.interactivity.modes.connect;
7659 if (!connect) {
7660 return;
7661 }
7662 container.retina.connectModeDistance = connect.distance * container.retina.pixelRatio;
7663 container.retina.connectModeRadius = connect.radius * container.retina.pixelRatio;
7664 }
7665 async interact() {
7666 const container = this.container,
7667 options = container.actualOptions;
7668 if (options.interactivity.events.onHover.enable && container.interactivity.status === "pointermove") {
7669 const mousePos = container.interactivity.mouse.position;
7670 if (!container.retina.connectModeDistance || container.retina.connectModeDistance < 0 || !container.retina.connectModeRadius || container.retina.connectModeRadius < 0 || !mousePos) {
7671 return;
7672 }
7673 const distance = Math.abs(container.retina.connectModeRadius),
7674 query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
7675 let i = 0;
7676 for (const p1 of query) {
7677 const pos1 = p1.getPosition();
7678 for (const p2 of query.slice(i + 1)) {
7679 const pos2 = p2.getPosition(),
7680 distMax = Math.abs(container.retina.connectModeDistance),
7681 xDiff = Math.abs(pos1.x - pos2.x),
7682 yDiff = Math.abs(pos1.y - pos2.y);
7683 if (xDiff < distMax && yDiff < distMax) {
7684 drawConnection(container, p1, p2);
7685 }
7686 }
7687 ++i;
7688 }
7689 }
7690 }
7691 isEnabled(particle) {
7692 const container = this.container,
7693 mouse = container.interactivity.mouse,
7694 events = (particle?.interactivity ?? container.actualOptions.interactivity).events;
7695 if (!(events.onHover.enable && mouse.position)) {
7696 return false;
7697 }
7698 return isInArray("connect", events.onHover.mode);
7699 }
7700 loadModeOptions(options, ...sources) {
7701 if (!options.connect) {
7702 options.connect = new Connect();
7703 }
7704 for (const source of sources) {
7705 options.connect.load(source?.connect);
7706 }
7707 }
7708 reset() {}
7709}
7710;// CONCATENATED MODULE: ../../interactions/external/connect/dist/esm/index.js
7711
7712async function loadExternalConnectInteraction(engine, refresh = true) {
7713 await engine.addInteractor("externalConnect", container => new Connector(container), refresh);
7714}
7715
7716
7717
7718
7719;// CONCATENATED MODULE: ../../interactions/external/grab/dist/esm/Options/Classes/GrabLinks.js
7720
7721class GrabLinks {
7722 constructor() {
7723 this.blink = false;
7724 this.consent = false;
7725 this.opacity = 1;
7726 }
7727 load(data) {
7728 if (!data) {
7729 return;
7730 }
7731 if (data.blink !== undefined) {
7732 this.blink = data.blink;
7733 }
7734 if (data.color !== undefined) {
7735 this.color = OptionsColor.create(this.color, data.color);
7736 }
7737 if (data.consent !== undefined) {
7738 this.consent = data.consent;
7739 }
7740 if (data.opacity !== undefined) {
7741 this.opacity = data.opacity;
7742 }
7743 }
7744}
7745;// CONCATENATED MODULE: ../../interactions/external/grab/dist/esm/Options/Classes/Grab.js
7746
7747class Grab {
7748 constructor() {
7749 this.distance = 100;
7750 this.links = new GrabLinks();
7751 }
7752 get lineLinked() {
7753 return this.links;
7754 }
7755 set lineLinked(value) {
7756 this.links = value;
7757 }
7758 get line_linked() {
7759 return this.links;
7760 }
7761 set line_linked(value) {
7762 this.links = value;
7763 }
7764 load(data) {
7765 if (!data) {
7766 return;
7767 }
7768 if (data.distance !== undefined) {
7769 this.distance = data.distance;
7770 }
7771 this.links.load(data.links ?? data.lineLinked ?? data.line_linked);
7772 }
7773}
7774;// CONCATENATED MODULE: ../../interactions/external/grab/dist/esm/Utils.js
7775
7776function drawGrabLine(context, width, begin, end, colorLine, opacity) {
7777 drawLine(context, begin, end);
7778 context.strokeStyle = getStyleFromRgb(colorLine, opacity);
7779 context.lineWidth = width;
7780 context.stroke();
7781}
7782function drawGrab(container, particle, lineColor, opacity, mousePos) {
7783 container.canvas.draw(ctx => {
7784 const beginPos = particle.getPosition();
7785 drawGrabLine(ctx, particle.retina.linksWidth ?? 0, beginPos, mousePos, lineColor, opacity);
7786 });
7787}
7788;// CONCATENATED MODULE: ../../interactions/external/grab/dist/esm/Grabber.js
7789
7790
7791
7792class Grabber extends ExternalInteractorBase {
7793 constructor(container) {
7794 super(container);
7795 }
7796 clear() {}
7797 init() {
7798 const container = this.container,
7799 grab = container.actualOptions.interactivity.modes.grab;
7800 if (!grab) {
7801 return;
7802 }
7803 container.retina.grabModeDistance = grab.distance * container.retina.pixelRatio;
7804 }
7805 async interact() {
7806 const container = this.container,
7807 options = container.actualOptions,
7808 interactivity = options.interactivity;
7809 if (!interactivity.modes.grab || !interactivity.events.onHover.enable || container.interactivity.status !== mouseMoveEvent) {
7810 return;
7811 }
7812 const mousePos = container.interactivity.mouse.position;
7813 if (!mousePos) {
7814 return;
7815 }
7816 const distance = container.retina.grabModeDistance;
7817 if (!distance || distance < 0) {
7818 return;
7819 }
7820 const query = container.particles.quadTree.queryCircle(mousePos, distance, p => this.isEnabled(p));
7821 for (const particle of query) {
7822 const pos = particle.getPosition(),
7823 pointDistance = getDistance(pos, mousePos);
7824 if (pointDistance > distance) {
7825 continue;
7826 }
7827 const grabLineOptions = interactivity.modes.grab.links,
7828 lineOpacity = grabLineOptions.opacity,
7829 opacityLine = lineOpacity - pointDistance * lineOpacity / distance;
7830 if (opacityLine <= 0) {
7831 continue;
7832 }
7833 const optColor = grabLineOptions.color ?? particle.options.links?.color;
7834 if (!container.particles.grabLineColor && optColor) {
7835 const linksOptions = interactivity.modes.grab.links;
7836 container.particles.grabLineColor = getLinkRandomColor(optColor, linksOptions.blink, linksOptions.consent);
7837 }
7838 const colorLine = getLinkColor(particle, undefined, container.particles.grabLineColor);
7839 if (!colorLine) {
7840 continue;
7841 }
7842 drawGrab(container, particle, colorLine, opacityLine, mousePos);
7843 }
7844 }
7845 isEnabled(particle) {
7846 const container = this.container,
7847 mouse = container.interactivity.mouse,
7848 events = (particle?.interactivity ?? container.actualOptions.interactivity).events;
7849 return events.onHover.enable && !!mouse.position && isInArray("grab", events.onHover.mode);
7850 }
7851 loadModeOptions(options, ...sources) {
7852 if (!options.grab) {
7853 options.grab = new Grab();
7854 }
7855 for (const source of sources) {
7856 options.grab.load(source?.grab);
7857 }
7858 }
7859 reset() {}
7860}
7861;// CONCATENATED MODULE: ../../interactions/external/grab/dist/esm/index.js
7862
7863async function loadExternalGrabInteraction(engine, refresh = true) {
7864 await engine.addInteractor("externalGrab", container => new Grabber(container), refresh);
7865}
7866
7867
7868
7869
7870;// CONCATENATED MODULE: ../../interactions/external/pause/dist/esm/Pauser.js
7871
7872class Pauser extends ExternalInteractorBase {
7873 constructor(container) {
7874 super(container);
7875 this.handleClickMode = mode => {
7876 if (mode !== "pause") {
7877 return;
7878 }
7879 const container = this.container;
7880 if (container.getAnimationStatus()) {
7881 container.pause();
7882 } else {
7883 container.play();
7884 }
7885 };
7886 }
7887 clear() {}
7888 init() {}
7889 async interact() {}
7890 isEnabled() {
7891 return true;
7892 }
7893 reset() {}
7894}
7895;// CONCATENATED MODULE: ../../interactions/external/pause/dist/esm/index.js
7896
7897async function loadExternalPauseInteraction(engine, refresh = true) {
7898 await engine.addInteractor("externalPause", container => new Pauser(container), refresh);
7899}
7900;// CONCATENATED MODULE: ../../interactions/external/push/dist/esm/Options/Classes/Push.js
7901
7902class Push {
7903 constructor() {
7904 this.default = true;
7905 this.groups = [];
7906 this.quantity = 4;
7907 }
7908 get particles_nb() {
7909 return this.quantity;
7910 }
7911 set particles_nb(value) {
7912 this.quantity = setRangeValue(value);
7913 }
7914 load(data) {
7915 if (!data) {
7916 return;
7917 }
7918 if (data.default !== undefined) {
7919 this.default = data.default;
7920 }
7921 if (data.groups !== undefined) {
7922 this.groups = data.groups.map(t => t);
7923 }
7924 if (!this.groups.length) {
7925 this.default = true;
7926 }
7927 const quantity = data.quantity ?? data.particles_nb;
7928 if (quantity !== undefined) {
7929 this.quantity = setRangeValue(quantity);
7930 }
7931 }
7932}
7933;// CONCATENATED MODULE: ../../interactions/external/push/dist/esm/Pusher.js
7934
7935
7936class Pusher extends ExternalInteractorBase {
7937 constructor(container) {
7938 super(container);
7939 this.handleClickMode = mode => {
7940 if (mode !== "push") {
7941 return;
7942 }
7943 const container = this.container,
7944 options = container.actualOptions,
7945 pushOptions = options.interactivity.modes.push;
7946 if (!pushOptions) {
7947 return;
7948 }
7949 const quantity = getRangeValue(pushOptions.quantity);
7950 if (quantity <= 0) {
7951 return;
7952 }
7953 const group = itemFromArray([undefined, ...pushOptions.groups]),
7954 groupOptions = group !== undefined ? container.actualOptions.particles.groups[group] : undefined;
7955 container.particles.push(quantity, container.interactivity.mouse, groupOptions, group);
7956 };
7957 }
7958 clear() {}
7959 init() {}
7960 async interact() {}
7961 isEnabled() {
7962 return true;
7963 }
7964 loadModeOptions(options, ...sources) {
7965 if (!options.push) {
7966 options.push = new Push();
7967 }
7968 for (const source of sources) {
7969 options.push.load(source?.push);
7970 }
7971 }
7972 reset() {}
7973}
7974;// CONCATENATED MODULE: ../../interactions/external/push/dist/esm/index.js
7975
7976async function loadExternalPushInteraction(engine, refresh = true) {
7977 await engine.addInteractor("externalPush", container => new Pusher(container), refresh);
7978}
7979
7980
7981;// CONCATENATED MODULE: ../../interactions/external/remove/dist/esm/Options/Classes/Remove.js
7982
7983class Remove {
7984 constructor() {
7985 this.quantity = 2;
7986 }
7987 get particles_nb() {
7988 return this.quantity;
7989 }
7990 set particles_nb(value) {
7991 this.quantity = setRangeValue(value);
7992 }
7993 load(data) {
7994 if (!data) {
7995 return;
7996 }
7997 const quantity = data.quantity ?? data.particles_nb;
7998 if (quantity !== undefined) {
7999 this.quantity = setRangeValue(quantity);
8000 }
8001 }
8002}
8003;// CONCATENATED MODULE: ../../interactions/external/remove/dist/esm/Remover.js
8004
8005
8006class Remover extends ExternalInteractorBase {
8007 constructor(container) {
8008 super(container);
8009 this.handleClickMode = mode => {
8010 const container = this.container,
8011 options = container.actualOptions;
8012 if (!options.interactivity.modes.remove || mode !== "remove") {
8013 return;
8014 }
8015 const removeNb = getRangeValue(options.interactivity.modes.remove.quantity);
8016 container.particles.removeQuantity(removeNb);
8017 };
8018 }
8019 clear() {}
8020 init() {}
8021 async interact() {}
8022 isEnabled() {
8023 return true;
8024 }
8025 loadModeOptions(options, ...sources) {
8026 if (!options.remove) {
8027 options.remove = new Remove();
8028 }
8029 for (const source of sources) {
8030 options.remove.load(source?.remove);
8031 }
8032 }
8033 reset() {}
8034}
8035;// CONCATENATED MODULE: ../../interactions/external/remove/dist/esm/index.js
8036
8037async function loadExternalRemoveInteraction(engine, refresh = true) {
8038 await engine.addInteractor("externalRemove", container => new Remover(container), refresh);
8039}
8040
8041
8042;// CONCATENATED MODULE: ../../interactions/external/repulse/dist/esm/Options/Classes/RepulseBase.js
8043class RepulseBase {
8044 constructor() {
8045 this.distance = 200;
8046 this.duration = 0.4;
8047 this.factor = 100;
8048 this.speed = 1;
8049 this.maxSpeed = 50;
8050 this.easing = "ease-out-quad";
8051 }
8052 load(data) {
8053 if (!data) {
8054 return;
8055 }
8056 if (data.distance !== undefined) {
8057 this.distance = data.distance;
8058 }
8059 if (data.duration !== undefined) {
8060 this.duration = data.duration;
8061 }
8062 if (data.easing !== undefined) {
8063 this.easing = data.easing;
8064 }
8065 if (data.factor !== undefined) {
8066 this.factor = data.factor;
8067 }
8068 if (data.speed !== undefined) {
8069 this.speed = data.speed;
8070 }
8071 if (data.maxSpeed !== undefined) {
8072 this.maxSpeed = data.maxSpeed;
8073 }
8074 }
8075}
8076;// CONCATENATED MODULE: ../../interactions/external/repulse/dist/esm/Options/Classes/RepulseDiv.js
8077
8078
8079class RepulseDiv extends RepulseBase {
8080 constructor() {
8081 super();
8082 this.selectors = [];
8083 }
8084 get ids() {
8085 return executeOnSingleOrMultiple(this.selectors, t => t.replace("#", ""));
8086 }
8087 set ids(value) {
8088 this.selectors = executeOnSingleOrMultiple(value, t => `#${t}`);
8089 }
8090 load(data) {
8091 super.load(data);
8092 if (!data) {
8093 return;
8094 }
8095 if (data.ids !== undefined) {
8096 this.ids = data.ids;
8097 }
8098 if (data.selectors !== undefined) {
8099 this.selectors = data.selectors;
8100 }
8101 }
8102}
8103;// CONCATENATED MODULE: ../../interactions/external/repulse/dist/esm/Options/Classes/Repulse.js
8104
8105
8106
8107class Repulse extends RepulseBase {
8108 load(data) {
8109 super.load(data);
8110 if (!data) {
8111 return;
8112 }
8113 this.divs = executeOnSingleOrMultiple(data.divs, div => {
8114 const tmp = new RepulseDiv();
8115 tmp.load(div);
8116 return tmp;
8117 });
8118 }
8119}
8120;// CONCATENATED MODULE: ../../interactions/external/repulse/dist/esm/Repulser.js
8121
8122
8123class Repulser extends ExternalInteractorBase {
8124 constructor(engine, container) {
8125 super(container);
8126 this._clickRepulse = () => {
8127 const container = this.container,
8128 repulseOptions = container.actualOptions.interactivity.modes.repulse;
8129 if (!repulseOptions) {
8130 return;
8131 }
8132 const repulse = container.repulse || {
8133 particles: []
8134 };
8135 if (!repulse.finish) {
8136 if (!repulse.count) {
8137 repulse.count = 0;
8138 }
8139 repulse.count++;
8140 if (repulse.count === container.particles.count) {
8141 repulse.finish = true;
8142 }
8143 }
8144 if (repulse.clicking) {
8145 const repulseDistance = container.retina.repulseModeDistance;
8146 if (!repulseDistance || repulseDistance < 0) {
8147 return;
8148 }
8149 const repulseRadius = Math.pow(repulseDistance / 6, 3),
8150 mouseClickPos = container.interactivity.mouse.clickPosition;
8151 if (mouseClickPos === undefined) {
8152 return;
8153 }
8154 const range = new Circle(mouseClickPos.x, mouseClickPos.y, repulseRadius),
8155 query = container.particles.quadTree.query(range, p => this.isEnabled(p));
8156 for (const particle of query) {
8157 const {
8158 dx,
8159 dy,
8160 distance
8161 } = getDistances(mouseClickPos, particle.position),
8162 d = distance ** 2,
8163 velocity = repulseOptions.speed,
8164 force = -repulseRadius * velocity / d;
8165 if (d <= repulseRadius) {
8166 repulse.particles.push(particle);
8167 const vect = Vector.create(dx, dy);
8168 vect.length = force;
8169 particle.velocity.setTo(vect);
8170 }
8171 }
8172 } else if (repulse.clicking === false) {
8173 for (const particle of repulse.particles) {
8174 particle.velocity.setTo(particle.initialVelocity);
8175 }
8176 repulse.particles = [];
8177 }
8178 };
8179 this._hoverRepulse = () => {
8180 const container = this.container,
8181 mousePos = container.interactivity.mouse.position,
8182 repulseRadius = container.retina.repulseModeDistance;
8183 if (!repulseRadius || repulseRadius < 0 || !mousePos) {
8184 return;
8185 }
8186 this._processRepulse(mousePos, repulseRadius, new Circle(mousePos.x, mousePos.y, repulseRadius));
8187 };
8188 this._processRepulse = (position, repulseRadius, area, divRepulse) => {
8189 const container = this.container,
8190 query = container.particles.quadTree.query(area, p => this.isEnabled(p)),
8191 repulseOptions = container.actualOptions.interactivity.modes.repulse;
8192 if (!repulseOptions) {
8193 return;
8194 }
8195 for (const particle of query) {
8196 const {
8197 dx,
8198 dy,
8199 distance
8200 } = getDistances(particle.position, position),
8201 velocity = (divRepulse?.speed ?? repulseOptions.speed) * repulseOptions.factor,
8202 repulseFactor = clamp(getEasing(repulseOptions.easing)(1 - distance / repulseRadius) * velocity, 0, repulseOptions.maxSpeed),
8203 normVec = Vector.create(distance === 0 ? velocity : dx / distance * repulseFactor, distance === 0 ? velocity : dy / distance * repulseFactor);
8204 particle.position.addTo(normVec);
8205 }
8206 };
8207 this._singleSelectorRepulse = (selector, div) => {
8208 const container = this.container,
8209 repulse = container.actualOptions.interactivity.modes.repulse;
8210 if (!repulse) {
8211 return;
8212 }
8213 const query = document.querySelectorAll(selector);
8214 if (!query.length) {
8215 return;
8216 }
8217 query.forEach(item => {
8218 const elem = item,
8219 pxRatio = container.retina.pixelRatio,
8220 pos = {
8221 x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
8222 y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio
8223 },
8224 repulseRadius = elem.offsetWidth / 2 * pxRatio,
8225 area = div.type === "circle" ? new Circle(pos.x, pos.y, repulseRadius) : new Rectangle(elem.offsetLeft * pxRatio, elem.offsetTop * pxRatio, elem.offsetWidth * pxRatio, elem.offsetHeight * pxRatio),
8226 divs = repulse.divs,
8227 divRepulse = divMode(divs, elem);
8228 this._processRepulse(pos, repulseRadius, area, divRepulse);
8229 });
8230 };
8231 this._engine = engine;
8232 if (!container.repulse) {
8233 container.repulse = {
8234 particles: []
8235 };
8236 }
8237 this.handleClickMode = mode => {
8238 const options = this.container.actualOptions,
8239 repulseOpts = options.interactivity.modes.repulse;
8240 if (!repulseOpts || mode !== "repulse") {
8241 return;
8242 }
8243 if (!container.repulse) {
8244 container.repulse = {
8245 particles: []
8246 };
8247 }
8248 const repulse = container.repulse;
8249 repulse.clicking = true;
8250 repulse.count = 0;
8251 for (const particle of container.repulse.particles) {
8252 if (!this.isEnabled(particle)) {
8253 continue;
8254 }
8255 particle.velocity.setTo(particle.initialVelocity);
8256 }
8257 repulse.particles = [];
8258 repulse.finish = false;
8259 setTimeout(() => {
8260 if (container.destroyed) {
8261 return;
8262 }
8263 repulse.clicking = false;
8264 }, repulseOpts.duration * 1000);
8265 };
8266 }
8267 clear() {}
8268 init() {
8269 const container = this.container,
8270 repulse = container.actualOptions.interactivity.modes.repulse;
8271 if (!repulse) {
8272 return;
8273 }
8274 container.retina.repulseModeDistance = repulse.distance * container.retina.pixelRatio;
8275 }
8276 async interact() {
8277 const container = this.container,
8278 options = container.actualOptions,
8279 mouseMoveStatus = container.interactivity.status === mouseMoveEvent,
8280 events = options.interactivity.events,
8281 hover = events.onHover,
8282 hoverEnabled = hover.enable,
8283 hoverMode = hover.mode,
8284 click = events.onClick,
8285 clickEnabled = click.enable,
8286 clickMode = click.mode,
8287 divs = events.onDiv;
8288 if (mouseMoveStatus && hoverEnabled && isInArray("repulse", hoverMode)) {
8289 this._hoverRepulse();
8290 } else if (clickEnabled && isInArray("repulse", clickMode)) {
8291 this._clickRepulse();
8292 } else {
8293 divModeExecute("repulse", divs, (selector, div) => this._singleSelectorRepulse(selector, div));
8294 }
8295 }
8296 isEnabled(particle) {
8297 const container = this.container,
8298 options = container.actualOptions,
8299 mouse = container.interactivity.mouse,
8300 events = (particle?.interactivity ?? options.interactivity).events,
8301 divs = events.onDiv,
8302 hover = events.onHover,
8303 click = events.onClick,
8304 divRepulse = isDivModeEnabled("repulse", divs);
8305 if (!(divRepulse || hover.enable && mouse.position || click.enable && mouse.clickPosition)) {
8306 return false;
8307 }
8308 const hoverMode = hover.mode,
8309 clickMode = click.mode;
8310 return isInArray("repulse", hoverMode) || isInArray("repulse", clickMode) || divRepulse;
8311 }
8312 loadModeOptions(options, ...sources) {
8313 if (!options.repulse) {
8314 options.repulse = new Repulse();
8315 }
8316 for (const source of sources) {
8317 options.repulse.load(source?.repulse);
8318 }
8319 }
8320 reset() {}
8321}
8322;// CONCATENATED MODULE: ../../interactions/external/repulse/dist/esm/index.js
8323
8324async function loadExternalRepulseInteraction(engine, refresh = true) {
8325 await engine.addInteractor("externalRepulse", container => new Repulser(engine, container), refresh);
8326}
8327
8328
8329
8330
8331
8332
8333;// CONCATENATED MODULE: ../../interactions/external/slow/dist/esm/Options/Classes/Slow.js
8334class Slow {
8335 constructor() {
8336 this.factor = 3;
8337 this.radius = 200;
8338 }
8339 load(data) {
8340 if (!data) {
8341 return;
8342 }
8343 if (data.factor !== undefined) {
8344 this.factor = data.factor;
8345 }
8346 if (data.radius !== undefined) {
8347 this.radius = data.radius;
8348 }
8349 }
8350}
8351;// CONCATENATED MODULE: ../../interactions/external/slow/dist/esm/Slower.js
8352
8353
8354class Slower extends ExternalInteractorBase {
8355 constructor(container) {
8356 super(container);
8357 }
8358 clear(particle, delta, force) {
8359 if (particle.slow.inRange && !force) {
8360 return;
8361 }
8362 particle.slow.factor = 1;
8363 }
8364 init() {
8365 const container = this.container,
8366 slow = container.actualOptions.interactivity.modes.slow;
8367 if (!slow) {
8368 return;
8369 }
8370 container.retina.slowModeRadius = slow.radius * container.retina.pixelRatio;
8371 }
8372 async interact() {}
8373 isEnabled(particle) {
8374 const container = this.container,
8375 mouse = container.interactivity.mouse,
8376 events = (particle?.interactivity ?? container.actualOptions.interactivity).events;
8377 return events.onHover.enable && !!mouse.position && isInArray("slow", events.onHover.mode);
8378 }
8379 loadModeOptions(options, ...sources) {
8380 if (!options.slow) {
8381 options.slow = new Slow();
8382 }
8383 for (const source of sources) {
8384 options.slow.load(source?.slow);
8385 }
8386 }
8387 reset(particle) {
8388 particle.slow.inRange = false;
8389 const container = this.container,
8390 options = container.actualOptions,
8391 mousePos = container.interactivity.mouse.position,
8392 radius = container.retina.slowModeRadius,
8393 slowOptions = options.interactivity.modes.slow;
8394 if (!slowOptions || !radius || radius < 0 || !mousePos) {
8395 return;
8396 }
8397 const particlePos = particle.getPosition(),
8398 dist = getDistance(mousePos, particlePos),
8399 proximityFactor = dist / radius,
8400 slowFactor = slowOptions.factor,
8401 {
8402 slow
8403 } = particle;
8404 if (dist > radius) {
8405 return;
8406 }
8407 slow.inRange = true;
8408 slow.factor = proximityFactor / slowFactor;
8409 }
8410}
8411;// CONCATENATED MODULE: ../../interactions/external/slow/dist/esm/index.js
8412
8413async function loadExternalSlowInteraction(engine, refresh = true) {
8414 await engine.addInteractor("externalSlow", container => new Slower(container), refresh);
8415}
8416
8417
8418;// CONCATENATED MODULE: ../../shapes/image/dist/esm/GifUtils/Constants.js
8419const InterlaceOffsets = [0, 4, 2, 1];
8420const InterlaceSteps = [8, 8, 4, 2];
8421;// CONCATENATED MODULE: ../../shapes/image/dist/esm/GifUtils/ByteStream.js
8422class ByteStream {
8423 constructor(bytes) {
8424 this.pos = 0;
8425 this.data = new Uint8ClampedArray(bytes);
8426 }
8427 getString(count) {
8428 const slice = this.data.slice(this.pos, this.pos + count);
8429 this.pos += slice.length;
8430 return slice.reduce((acc, curr) => acc + String.fromCharCode(curr), "");
8431 }
8432 nextByte() {
8433 return this.data[this.pos++];
8434 }
8435 nextTwoBytes() {
8436 this.pos += 2;
8437 return this.data[this.pos - 2] + (this.data[this.pos - 1] << 8);
8438 }
8439 readSubBlocks() {
8440 let blockString = "",
8441 size = 0;
8442 do {
8443 size = this.data[this.pos++];
8444 for (let count = size; --count >= 0; blockString += String.fromCharCode(this.data[this.pos++])) {}
8445 } while (size !== 0);
8446 return blockString;
8447 }
8448 readSubBlocksBin() {
8449 let size = 0,
8450 len = 0;
8451 for (let offset = 0; (size = this.data[this.pos + offset]) !== 0; offset += size + 1) {
8452 len += size;
8453 }
8454 const blockData = new Uint8Array(len);
8455 for (let i = 0; (size = this.data[this.pos++]) !== 0;) {
8456 for (let count = size; --count >= 0; blockData[i++] = this.data[this.pos++]) {}
8457 }
8458 return blockData;
8459 }
8460 skipSubBlocks() {
8461 for (; this.data[this.pos] !== 0; this.pos += this.data[this.pos] + 1) {}
8462 this.pos++;
8463 }
8464}
8465;// CONCATENATED MODULE: ../../shapes/image/dist/esm/GifUtils/Utils.js
8466
8467
8468function parseColorTable(byteStream, count) {
8469 const colors = [];
8470 for (let i = 0; i < count; i++) {
8471 colors.push({
8472 r: byteStream.data[byteStream.pos],
8473 g: byteStream.data[byteStream.pos + 1],
8474 b: byteStream.data[byteStream.pos + 2]
8475 });
8476 byteStream.pos += 3;
8477 }
8478 return colors;
8479}
8480async function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
8481 switch (byteStream.nextByte()) {
8482 case 249:
8483 {
8484 const frame = gif.frames[getFrameIndex(false)];
8485 byteStream.pos++;
8486 const packedByte = byteStream.nextByte();
8487 frame.GCreserved = (packedByte & 0xe0) >>> 5;
8488 frame.disposalMethod = (packedByte & 0x1c) >>> 2;
8489 frame.userInputDelayFlag = (packedByte & 2) === 2;
8490 const transparencyFlag = (packedByte & 1) === 1;
8491 frame.delayTime = byteStream.nextTwoBytes() * 0xa;
8492 const transparencyIndex = byteStream.nextByte();
8493 if (transparencyFlag) {
8494 getTransparencyIndex(transparencyIndex);
8495 }
8496 byteStream.pos++;
8497 break;
8498 }
8499 case 255:
8500 {
8501 byteStream.pos++;
8502 const applicationExtension = {
8503 identifier: byteStream.getString(8),
8504 authenticationCode: byteStream.getString(3),
8505 data: byteStream.readSubBlocksBin()
8506 };
8507 gif.applicationExtensions.push(applicationExtension);
8508 break;
8509 }
8510 case 254:
8511 {
8512 gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);
8513 break;
8514 }
8515 case 1:
8516 {
8517 if (gif.globalColorTable.length === 0) {
8518 throw new EvalError("plain text extension without global color table");
8519 }
8520 byteStream.pos++;
8521 gif.frames[getFrameIndex(false)].plainTextData = {
8522 left: byteStream.nextTwoBytes(),
8523 top: byteStream.nextTwoBytes(),
8524 width: byteStream.nextTwoBytes(),
8525 height: byteStream.nextTwoBytes(),
8526 charSize: {
8527 width: byteStream.nextTwoBytes(),
8528 height: byteStream.nextTwoBytes()
8529 },
8530 foregroundColor: byteStream.nextByte(),
8531 backgroundColor: byteStream.nextByte(),
8532 text: byteStream.readSubBlocks()
8533 };
8534 break;
8535 }
8536 default:
8537 byteStream.skipSubBlocks();
8538 break;
8539 }
8540}
8541async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback) {
8542 const frame = gif.frames[getFrameIndex(true)];
8543 frame.left = byteStream.nextTwoBytes();
8544 frame.top = byteStream.nextTwoBytes();
8545 frame.width = byteStream.nextTwoBytes();
8546 frame.height = byteStream.nextTwoBytes();
8547 const packedByte = byteStream.nextByte(),
8548 localColorTableFlag = (packedByte & 0x80) === 0x80,
8549 interlacedFlag = (packedByte & 0x40) === 0x40;
8550 frame.sortFlag = (packedByte & 0x20) === 0x20;
8551 frame.reserved = (packedByte & 0x18) >>> 3;
8552 const localColorCount = 1 << (packedByte & 7) + 1;
8553 if (localColorTableFlag) {
8554 frame.localColorTable = parseColorTable(byteStream, localColorCount);
8555 }
8556 const getColor = index => {
8557 const {
8558 r,
8559 g,
8560 b
8561 } = (localColorTableFlag ? frame.localColorTable : gif.globalColorTable)[index];
8562 return {
8563 r,
8564 g,
8565 b,
8566 a: index === getTransparencyIndex(null) ? avgAlpha ? ~~((r + g + b) / 3) : 0 : 255
8567 };
8568 };
8569 const image = (() => {
8570 try {
8571 return new ImageData(frame.width, frame.height, {
8572 colorSpace: "srgb"
8573 });
8574 } catch (error) {
8575 if (error instanceof DOMException && error.name === "IndexSizeError") {
8576 return null;
8577 }
8578 throw error;
8579 }
8580 })();
8581 if (image == null) {
8582 throw new EvalError("GIF frame size is to large");
8583 }
8584 const minCodeSize = byteStream.nextByte(),
8585 imageData = byteStream.readSubBlocksBin(),
8586 clearCode = 1 << minCodeSize;
8587 const readBits = (pos, len) => {
8588 const bytePos = pos >>> 3,
8589 bitPos = pos & 7;
8590 return (imageData[bytePos] + (imageData[bytePos + 1] << 8) + (imageData[bytePos + 2] << 16) & (1 << len) - 1 << bitPos) >>> bitPos;
8591 };
8592 if (interlacedFlag) {
8593 for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pass = 0; pass < 4; pass++) {
8594 if (InterlaceOffsets[pass] < frame.height) {
8595 for (let pixelPos = 0, lineIndex = 0;;) {
8596 const last = code;
8597 code = readBits(pos, size);
8598 pos += size + 1;
8599 if (code === clearCode) {
8600 size = minCodeSize + 1;
8601 dic.length = clearCode + 2;
8602 for (let i = 0; i < dic.length; i++) {
8603 dic[i] = i < clearCode ? [i] : [];
8604 }
8605 } else {
8606 if (code >= dic.length) {
8607 dic.push(dic[last].concat(dic[last][0]));
8608 } else if (last !== clearCode) {
8609 dic.push(dic[last].concat(dic[code][0]));
8610 }
8611 for (let i = 0; i < dic[code].length; i++) {
8612 const {
8613 r,
8614 g,
8615 b,
8616 a
8617 } = getColor(dic[code][i]);
8618 image.data.set([r, g, b, a], InterlaceOffsets[pass] * frame.width + InterlaceSteps[pass] * lineIndex + pixelPos % (frame.width * 4));
8619 pixelPos += 4;
8620 }
8621 if (dic.length === 1 << size && size < 0xc) {
8622 size++;
8623 }
8624 }
8625 if (pixelPos === frame.width * 4 * (lineIndex + 1)) {
8626 lineIndex++;
8627 if (InterlaceOffsets[pass] + InterlaceSteps[pass] * lineIndex >= frame.height) {
8628 break;
8629 }
8630 }
8631 }
8632 }
8633 progressCallback?.(byteStream.pos / (byteStream.data.length - 1), getFrameIndex(false) + 1, image, {
8634 x: frame.left,
8635 y: frame.top
8636 }, {
8637 width: gif.width,
8638 height: gif.height
8639 });
8640 }
8641 frame.image = image;
8642 frame.bitmap = await createImageBitmap(image);
8643 } else {
8644 for (let code = 0, size = minCodeSize + 1, pos = 0, dic = [[0]], pixelPos = -4;;) {
8645 const last = code;
8646 code = readBits(pos, size);
8647 pos += size;
8648 if (code === clearCode) {
8649 size = minCodeSize + 1;
8650 dic.length = clearCode + 2;
8651 for (let i = 0; i < dic.length; i++) {
8652 dic[i] = i < clearCode ? [i] : [];
8653 }
8654 } else {
8655 if (code === clearCode + 1) {
8656 break;
8657 }
8658 if (code >= dic.length) {
8659 dic.push(dic[last].concat(dic[last][0]));
8660 } else if (last !== clearCode) {
8661 dic.push(dic[last].concat(dic[code][0]));
8662 }
8663 for (let i = 0; i < dic[code].length; i++) {
8664 const {
8665 r,
8666 g,
8667 b,
8668 a
8669 } = getColor(dic[code][i]);
8670 image.data.set([r, g, b, a], pixelPos += 4);
8671 }
8672 if (dic.length >= 1 << size && size < 0xc) {
8673 size++;
8674 }
8675 }
8676 }
8677 frame.image = image;
8678 frame.bitmap = await createImageBitmap(image);
8679 progressCallback?.((byteStream.pos + 1) / byteStream.data.length, getFrameIndex(false) + 1, frame.image, {
8680 x: frame.left,
8681 y: frame.top
8682 }, {
8683 width: gif.width,
8684 height: gif.height
8685 });
8686 }
8687}
8688async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback) {
8689 switch (byteStream.nextByte()) {
8690 case 59:
8691 return true;
8692 case 44:
8693 await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
8694 break;
8695 case 33:
8696 await parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
8697 break;
8698 default:
8699 throw new EvalError("undefined block found");
8700 }
8701 return false;
8702}
8703function getGIFLoopAmount(gif) {
8704 for (const extension of gif.applicationExtensions) {
8705 if (extension.identifier + extension.authenticationCode !== "NETSCAPE2.0") {
8706 continue;
8707 }
8708 return extension.data[1] + (extension.data[2] << 8);
8709 }
8710 return NaN;
8711}
8712async function decodeGIF(gifURL, progressCallback, avgAlpha) {
8713 if (!avgAlpha) avgAlpha = false;
8714 const res = await fetch(gifURL);
8715 if (!res.ok && res.status === 404) {
8716 throw new EvalError("file not found");
8717 }
8718 const buffer = await res.arrayBuffer();
8719 const gif = {
8720 width: 0,
8721 height: 0,
8722 totalTime: 0,
8723 colorRes: 0,
8724 pixelAspectRatio: 0,
8725 frames: [],
8726 sortFlag: false,
8727 globalColorTable: [],
8728 backgroundImage: new ImageData(1, 1, {
8729 colorSpace: "srgb"
8730 }),
8731 comments: [],
8732 applicationExtensions: []
8733 },
8734 byteStream = new ByteStream(new Uint8ClampedArray(buffer));
8735 if (byteStream.getString(6) !== "GIF89a") {
8736 throw new Error("not a supported GIF file");
8737 }
8738 gif.width = byteStream.nextTwoBytes();
8739 gif.height = byteStream.nextTwoBytes();
8740 const packedByte = byteStream.nextByte(),
8741 globalColorTableFlag = (packedByte & 0x80) === 0x80;
8742 gif.colorRes = (packedByte & 0x70) >>> 4;
8743 gif.sortFlag = (packedByte & 8) === 8;
8744 const globalColorCount = 1 << (packedByte & 7) + 1,
8745 backgroundColorIndex = byteStream.nextByte();
8746 gif.pixelAspectRatio = byteStream.nextByte();
8747 if (gif.pixelAspectRatio !== 0) {
8748 gif.pixelAspectRatio = (gif.pixelAspectRatio + 0xf) / 0x40;
8749 }
8750 if (globalColorTableFlag) {
8751 gif.globalColorTable = parseColorTable(byteStream, globalColorCount);
8752 }
8753 const backgroundImage = (() => {
8754 try {
8755 return new ImageData(gif.width, gif.height, {
8756 colorSpace: "srgb"
8757 });
8758 } catch (error) {
8759 if (error instanceof DOMException && error.name === "IndexSizeError") {
8760 return null;
8761 }
8762 throw error;
8763 }
8764 })();
8765 if (backgroundImage == null) {
8766 throw new Error("GIF frame size is to large");
8767 }
8768 const {
8769 r,
8770 g,
8771 b
8772 } = gif.globalColorTable[backgroundColorIndex];
8773 backgroundImage.data.set(globalColorTableFlag ? [r, g, b, 255] : [0, 0, 0, 0]);
8774 for (let i = 4; i < backgroundImage.data.length; i *= 2) {
8775 backgroundImage.data.copyWithin(i, 0, i);
8776 }
8777 gif.backgroundImage = backgroundImage;
8778 let frameIndex = -1,
8779 incrementFrameIndex = true,
8780 transparencyIndex = -1;
8781 const getframeIndex = increment => {
8782 if (increment) {
8783 incrementFrameIndex = true;
8784 }
8785 return frameIndex;
8786 };
8787 const getTransparencyIndex = newValue => {
8788 if (newValue != null) {
8789 transparencyIndex = newValue;
8790 }
8791 return transparencyIndex;
8792 };
8793 try {
8794 do {
8795 if (incrementFrameIndex) {
8796 gif.frames.push({
8797 left: 0,
8798 top: 0,
8799 width: 0,
8800 height: 0,
8801 disposalMethod: 0,
8802 image: new ImageData(1, 1, {
8803 colorSpace: "srgb"
8804 }),
8805 plainTextData: null,
8806 userInputDelayFlag: false,
8807 delayTime: 0,
8808 sortFlag: false,
8809 localColorTable: [],
8810 reserved: 0,
8811 GCreserved: 0
8812 });
8813 frameIndex++;
8814 transparencyIndex = -1;
8815 incrementFrameIndex = false;
8816 }
8817 } while (!(await parseBlock(byteStream, gif, avgAlpha, getframeIndex, getTransparencyIndex, progressCallback)));
8818 gif.frames.length--;
8819 for (const frame of gif.frames) {
8820 if (frame.userInputDelayFlag && frame.delayTime === 0) {
8821 gif.totalTime = Infinity;
8822 break;
8823 }
8824 gif.totalTime += frame.delayTime;
8825 }
8826 return gif;
8827 } catch (error) {
8828 if (error instanceof EvalError) {
8829 throw new Error(`error while parsing frame ${frameIndex} "${error.message}"`);
8830 }
8831 throw error;
8832 }
8833}
8834;// CONCATENATED MODULE: ../../shapes/image/dist/esm/Utils.js
8835
8836
8837const currentColorRegex = /(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?\))|currentcolor/gi;
8838function replaceColorSvg(imageShape, color, opacity) {
8839 const {
8840 svgData
8841 } = imageShape;
8842 if (!svgData) {
8843 return "";
8844 }
8845 const colorStyle = getStyleFromHsl(color, opacity);
8846 if (svgData.includes("fill")) {
8847 return svgData.replace(currentColorRegex, () => colorStyle);
8848 }
8849 const preFillIndex = svgData.indexOf(">");
8850 return `${svgData.substring(0, preFillIndex)} fill="${colorStyle}"${svgData.substring(preFillIndex)}`;
8851}
8852async function loadImage(image) {
8853 return new Promise(resolve => {
8854 image.loading = true;
8855 const img = new Image();
8856 image.element = img;
8857 img.addEventListener("load", () => {
8858 image.loading = false;
8859 resolve();
8860 });
8861 img.addEventListener("error", () => {
8862 image.element = undefined;
8863 image.error = true;
8864 image.loading = false;
8865 getLogger().error(`${errorPrefix} loading image: ${image.source}`);
8866 resolve();
8867 });
8868 img.src = image.source;
8869 });
8870}
8871async function loadGifImage(image) {
8872 if (image.type !== "gif") {
8873 await loadImage(image);
8874 return;
8875 }
8876 image.loading = true;
8877 try {
8878 image.gifData = await decodeGIF(image.source);
8879 image.gifLoopCount = getGIFLoopAmount(image.gifData) ?? 0;
8880 if (image.gifLoopCount === 0) {
8881 image.gifLoopCount = Infinity;
8882 }
8883 } catch {
8884 image.error = true;
8885 }
8886 image.loading = false;
8887}
8888async function downloadSvgImage(image) {
8889 if (image.type !== "svg") {
8890 await loadImage(image);
8891 return;
8892 }
8893 image.loading = true;
8894 const response = await fetch(image.source);
8895 if (!response.ok) {
8896 getLogger().error(`${errorPrefix} Image not found`);
8897 image.error = true;
8898 } else {
8899 image.svgData = await response.text();
8900 }
8901 image.loading = false;
8902}
8903function replaceImageColor(image, imageData, color, particle) {
8904 const svgColoredData = replaceColorSvg(image, color, particle.opacity?.value ?? 1),
8905 imageRes = {
8906 color,
8907 gif: imageData.gif,
8908 data: {
8909 ...image,
8910 svgData: svgColoredData
8911 },
8912 loaded: false,
8913 ratio: imageData.width / imageData.height,
8914 replaceColor: imageData.replaceColor ?? imageData.replace_color,
8915 source: imageData.src
8916 };
8917 return new Promise(resolve => {
8918 const svg = new Blob([svgColoredData], {
8919 type: "image/svg+xml"
8920 }),
8921 domUrl = URL || window.URL || window.webkitURL || window,
8922 url = domUrl.createObjectURL(svg),
8923 img = new Image();
8924 img.addEventListener("load", () => {
8925 imageRes.loaded = true;
8926 imageRes.element = img;
8927 resolve(imageRes);
8928 domUrl.revokeObjectURL(url);
8929 });
8930 img.addEventListener("error", async () => {
8931 domUrl.revokeObjectURL(url);
8932 const img2 = {
8933 ...image,
8934 error: false,
8935 loading: true
8936 };
8937 await loadImage(img2);
8938 imageRes.loaded = true;
8939 imageRes.element = img2.element;
8940 resolve(imageRes);
8941 });
8942 img.src = url;
8943 });
8944}
8945;// CONCATENATED MODULE: ../../shapes/image/dist/esm/ImageDrawer.js
8946
8947
8948class ImageDrawer {
8949 constructor(engine) {
8950 this.loadImageShape = async imageShape => {
8951 if (!this._engine.loadImage) {
8952 throw new Error(`${errorPrefix} image shape not initialized`);
8953 }
8954 await this._engine.loadImage({
8955 gif: imageShape.gif,
8956 name: imageShape.name,
8957 replaceColor: imageShape.replaceColor ?? imageShape.replace_color ?? false,
8958 src: imageShape.src
8959 });
8960 };
8961 this._engine = engine;
8962 }
8963 addImage(image) {
8964 if (!this._engine.images) {
8965 this._engine.images = [];
8966 }
8967 this._engine.images.push(image);
8968 }
8969 draw(context, particle, radius, opacity, delta) {
8970 const image = particle.image,
8971 element = image?.element;
8972 if (!image) {
8973 return;
8974 }
8975 context.globalAlpha = opacity;
8976 if (image.gif && image.gifData) {
8977 const offscreenCanvas = new OffscreenCanvas(image.gifData.width, image.gifData.height),
8978 offscreenContext = offscreenCanvas.getContext("2d");
8979 if (!offscreenContext) {
8980 throw new Error("could not create offscreen canvas context");
8981 }
8982 offscreenContext.imageSmoothingQuality = "low";
8983 offscreenContext.imageSmoothingEnabled = false;
8984 offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
8985 if (particle.gifLoopCount === undefined) {
8986 particle.gifLoopCount = image.gifLoopCount ?? 0;
8987 }
8988 let frameIndex = particle.gifFrame ?? 0;
8989 const pos = {
8990 x: -image.gifData.width * 0.5,
8991 y: -image.gifData.height * 0.5
8992 },
8993 frame = image.gifData.frames[frameIndex];
8994 if (particle.gifTime === undefined) {
8995 particle.gifTime = 0;
8996 }
8997 if (!frame.bitmap) {
8998 return;
8999 }
9000 context.scale(radius / image.gifData.width, radius / image.gifData.height);
9001 switch (frame.disposalMethod) {
9002 case 4:
9003 case 5:
9004 case 6:
9005 case 7:
9006 case 0:
9007 offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
9008 context.drawImage(offscreenCanvas, pos.x, pos.y);
9009 offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
9010 break;
9011 case 1:
9012 offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
9013 context.drawImage(offscreenCanvas, pos.x, pos.y);
9014 break;
9015 case 2:
9016 offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
9017 context.drawImage(offscreenCanvas, pos.x, pos.y);
9018 offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
9019 if (image.gifData.globalColorTable.length === 0) {
9020 offscreenContext.putImageData(image.gifData.frames[0].image, pos.x + frame.left, pos.y + frame.top);
9021 } else {
9022 offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
9023 }
9024 break;
9025 case 3:
9026 {
9027 const previousImageData = offscreenContext.getImageData(0, 0, offscreenCanvas.width, offscreenCanvas.height);
9028 offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
9029 context.drawImage(offscreenCanvas, pos.x, pos.y);
9030 offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
9031 offscreenContext.putImageData(previousImageData, 0, 0);
9032 }
9033 break;
9034 }
9035 particle.gifTime += delta.value;
9036 if (particle.gifTime > frame.delayTime) {
9037 particle.gifTime -= frame.delayTime;
9038 if (++frameIndex >= image.gifData.frames.length) {
9039 if (--particle.gifLoopCount <= 0) {
9040 return;
9041 }
9042 frameIndex = 0;
9043 offscreenContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
9044 }
9045 particle.gifFrame = frameIndex;
9046 }
9047 context.scale(image.gifData.width / radius, image.gifData.height / radius);
9048 } else if (element) {
9049 const ratio = image.ratio,
9050 pos = {
9051 x: -radius,
9052 y: -radius
9053 };
9054 context.drawImage(element, pos.x, pos.y, radius * 2, radius * 2 / ratio);
9055 }
9056 context.globalAlpha = 1;
9057 }
9058 getSidesCount() {
9059 return 12;
9060 }
9061 async init(container) {
9062 const options = container.actualOptions;
9063 if (!options.preload || !this._engine.loadImage) {
9064 return;
9065 }
9066 for (const imageData of options.preload) {
9067 await this._engine.loadImage(imageData);
9068 }
9069 }
9070 loadShape(particle) {
9071 if (particle.shape !== "image" && particle.shape !== "images") {
9072 return;
9073 }
9074 if (!this._engine.images) {
9075 this._engine.images = [];
9076 }
9077 const imageData = particle.shapeData,
9078 image = this._engine.images.find(t => t.name === imageData.name || t.source === imageData.src);
9079 if (!image) {
9080 this.loadImageShape(imageData).then(() => {
9081 this.loadShape(particle);
9082 });
9083 }
9084 }
9085 particleInit(container, particle) {
9086 if (particle.shape !== "image" && particle.shape !== "images") {
9087 return;
9088 }
9089 if (!this._engine.images) {
9090 this._engine.images = [];
9091 }
9092 const images = this._engine.images,
9093 imageData = particle.shapeData,
9094 color = particle.getFillColor(),
9095 image = images.find(t => t.name === imageData.name || t.source === imageData.src);
9096 if (!image) {
9097 return;
9098 }
9099 const replaceColor = imageData.replaceColor ?? imageData.replace_color ?? image.replaceColor;
9100 if (image.loading) {
9101 setTimeout(() => {
9102 this.particleInit(container, particle);
9103 });
9104 return;
9105 }
9106 (async () => {
9107 let imageRes;
9108 if (image.svgData && color) {
9109 imageRes = await replaceImageColor(image, imageData, color, particle);
9110 } else {
9111 imageRes = {
9112 color,
9113 data: image,
9114 element: image.element,
9115 gif: image.gif,
9116 gifData: image.gifData,
9117 gifLoopCount: image.gifLoopCount,
9118 loaded: true,
9119 ratio: imageData.width && imageData.height ? imageData.width / imageData.height : image.ratio ?? 1,
9120 replaceColor: replaceColor,
9121 source: imageData.src
9122 };
9123 }
9124 if (!imageRes.ratio) {
9125 imageRes.ratio = 1;
9126 }
9127 const fill = imageData.fill ?? particle.fill,
9128 close = imageData.close ?? particle.close,
9129 imageShape = {
9130 image: imageRes,
9131 fill,
9132 close
9133 };
9134 particle.image = imageShape.image;
9135 particle.fill = imageShape.fill;
9136 particle.close = imageShape.close;
9137 })();
9138 }
9139}
9140;// CONCATENATED MODULE: ../../shapes/image/dist/esm/Options/Classes/Preload.js
9141class Preload {
9142 constructor() {
9143 this.src = "";
9144 this.gif = false;
9145 }
9146 load(data) {
9147 if (!data) {
9148 return;
9149 }
9150 if (data.gif !== undefined) {
9151 this.gif = data.gif;
9152 }
9153 if (data.height !== undefined) {
9154 this.height = data.height;
9155 }
9156 if (data.name !== undefined) {
9157 this.name = data.name;
9158 }
9159 if (data.replaceColor !== undefined) {
9160 this.replaceColor = data.replaceColor;
9161 }
9162 if (data.src !== undefined) {
9163 this.src = data.src;
9164 }
9165 if (data.width !== undefined) {
9166 this.width = data.width;
9167 }
9168 }
9169}
9170;// CONCATENATED MODULE: ../../shapes/image/dist/esm/ImagePreloader.js
9171
9172class ImagePreloaderPlugin {
9173 constructor(engine) {
9174 this.id = "imagePreloader";
9175 this._engine = engine;
9176 }
9177 getPlugin() {
9178 return {};
9179 }
9180 loadOptions(options, source) {
9181 if (!source || !source.preload) {
9182 return;
9183 }
9184 if (!options.preload) {
9185 options.preload = [];
9186 }
9187 const preloadOptions = options.preload;
9188 for (const item of source.preload) {
9189 const existing = preloadOptions.find(t => t.name === item.name || t.src === item.src);
9190 if (existing) {
9191 existing.load(item);
9192 } else {
9193 const preload = new Preload();
9194 preload.load(item);
9195 preloadOptions.push(preload);
9196 }
9197 }
9198 }
9199 needsPlugin() {
9200 return true;
9201 }
9202}
9203;// CONCATENATED MODULE: ../../shapes/image/dist/esm/index.js
9204
9205
9206
9207
9208function addLoadImageToEngine(engine) {
9209 if (engine.loadImage) {
9210 return;
9211 }
9212 engine.loadImage = async data => {
9213 if (!data.name && !data.src) {
9214 throw new Error(`${errorPrefix} no image source provided`);
9215 }
9216 if (!engine.images) {
9217 engine.images = [];
9218 }
9219 if (engine.images.find(t => t.name === data.name || t.source === data.src)) {
9220 return;
9221 }
9222 try {
9223 const image = {
9224 gif: data.gif ?? false,
9225 name: data.name ?? data.src,
9226 source: data.src,
9227 type: data.src.substring(data.src.length - 3),
9228 error: false,
9229 loading: true,
9230 replaceColor: data.replaceColor,
9231 ratio: data.width && data.height ? data.width / data.height : undefined
9232 };
9233 engine.images.push(image);
9234 const imageFunc = data.gif ? loadGifImage : data.replaceColor ? downloadSvgImage : loadImage;
9235 await imageFunc(image);
9236 } catch {
9237 throw new Error(`${errorPrefix} ${data.name ?? data.src} not found`);
9238 }
9239 };
9240}
9241async function loadImageShape(engine, refresh = true) {
9242 addLoadImageToEngine(engine);
9243 const preloader = new ImagePreloaderPlugin(engine);
9244 await engine.addPlugin(preloader, refresh);
9245 await engine.addShape(["image", "images"], new ImageDrawer(engine), refresh);
9246}
9247;// CONCATENATED MODULE: ../../updaters/life/dist/esm/Options/Classes/LifeDelay.js
9248
9249class LifeDelay extends ValueWithRandom {
9250 constructor() {
9251 super();
9252 this.sync = false;
9253 }
9254 load(data) {
9255 if (!data) {
9256 return;
9257 }
9258 super.load(data);
9259 if (data.sync !== undefined) {
9260 this.sync = data.sync;
9261 }
9262 }
9263}
9264;// CONCATENATED MODULE: ../../updaters/life/dist/esm/Options/Classes/LifeDuration.js
9265
9266class LifeDuration extends ValueWithRandom {
9267 constructor() {
9268 super();
9269 this.random.minimumValue = 0.0001;
9270 this.sync = false;
9271 }
9272 load(data) {
9273 if (!data) {
9274 return;
9275 }
9276 super.load(data);
9277 if (data.sync !== undefined) {
9278 this.sync = data.sync;
9279 }
9280 }
9281}
9282;// CONCATENATED MODULE: ../../updaters/life/dist/esm/Options/Classes/Life.js
9283
9284
9285class Life {
9286 constructor() {
9287 this.count = 0;
9288 this.delay = new LifeDelay();
9289 this.duration = new LifeDuration();
9290 }
9291 load(data) {
9292 if (!data) {
9293 return;
9294 }
9295 if (data.count !== undefined) {
9296 this.count = data.count;
9297 }
9298 this.delay.load(data.delay);
9299 this.duration.load(data.duration);
9300 }
9301}
9302;// CONCATENATED MODULE: ../../updaters/life/dist/esm/LifeUpdater.js
9303
9304
9305class LifeUpdater {
9306 constructor(container) {
9307 this.container = container;
9308 }
9309 init(particle) {
9310 const container = this.container,
9311 particlesOptions = particle.options,
9312 lifeOptions = particlesOptions.life;
9313 if (!lifeOptions) {
9314 return;
9315 }
9316 particle.life = {
9317 delay: container.retina.reduceFactor ? getRangeValue(lifeOptions.delay.value) * (lifeOptions.delay.sync ? 1 : getRandom()) / container.retina.reduceFactor * 1000 : 0,
9318 delayTime: 0,
9319 duration: container.retina.reduceFactor ? getRangeValue(lifeOptions.duration.value) * (lifeOptions.duration.sync ? 1 : getRandom()) / container.retina.reduceFactor * 1000 : 0,
9320 time: 0,
9321 count: lifeOptions.count
9322 };
9323 if (particle.life.duration <= 0) {
9324 particle.life.duration = -1;
9325 }
9326 if (particle.life.count <= 0) {
9327 particle.life.count = -1;
9328 }
9329 if (particle.life) {
9330 particle.spawning = particle.life.delay > 0;
9331 }
9332 }
9333 isEnabled(particle) {
9334 return !particle.destroyed;
9335 }
9336 loadOptions(options, ...sources) {
9337 if (!options.life) {
9338 options.life = new Life();
9339 }
9340 for (const source of sources) {
9341 options.life.load(source?.life);
9342 }
9343 }
9344 update(particle, delta) {
9345 if (!this.isEnabled(particle) || !particle.life) {
9346 return;
9347 }
9348 const life = particle.life;
9349 let justSpawned = false;
9350 if (particle.spawning) {
9351 life.delayTime += delta.value;
9352 if (life.delayTime >= particle.life.delay) {
9353 justSpawned = true;
9354 particle.spawning = false;
9355 life.delayTime = 0;
9356 life.time = 0;
9357 } else {
9358 return;
9359 }
9360 }
9361 if (life.duration === -1) {
9362 return;
9363 }
9364 if (particle.spawning) {
9365 return;
9366 }
9367 if (justSpawned) {
9368 life.time = 0;
9369 } else {
9370 life.time += delta.value;
9371 }
9372 if (life.time < life.duration) {
9373 return;
9374 }
9375 life.time = 0;
9376 if (particle.life.count > 0) {
9377 particle.life.count--;
9378 }
9379 if (particle.life.count === 0) {
9380 particle.destroy();
9381 return;
9382 }
9383 const canvasSize = this.container.canvas.size,
9384 widthRange = setRangeValue(0, canvasSize.width),
9385 heightRange = setRangeValue(0, canvasSize.width);
9386 particle.position.x = randomInRange(widthRange);
9387 particle.position.y = randomInRange(heightRange);
9388 particle.spawning = true;
9389 life.delayTime = 0;
9390 life.time = 0;
9391 particle.reset();
9392 const lifeOptions = particle.options.life;
9393 if (lifeOptions) {
9394 life.delay = getRangeValue(lifeOptions.delay.value) * 1000;
9395 life.duration = getRangeValue(lifeOptions.duration.value) * 1000;
9396 }
9397 }
9398}
9399;// CONCATENATED MODULE: ../../updaters/life/dist/esm/index.js
9400
9401async function loadLifeUpdater(engine, refresh = true) {
9402 await engine.addParticleUpdater("life", container => new LifeUpdater(container), refresh);
9403}
9404;// CONCATENATED MODULE: ../../shapes/line/dist/esm/LineDrawer.js
9405class LineDrawer {
9406 draw(context, particle, radius) {
9407 const shapeData = particle.shapeData;
9408 context.moveTo(-radius / 2, 0);
9409 context.lineTo(radius / 2, 0);
9410 context.lineCap = shapeData?.cap ?? "butt";
9411 }
9412 getSidesCount() {
9413 return 1;
9414 }
9415}
9416;// CONCATENATED MODULE: ../../shapes/line/dist/esm/index.js
9417
9418async function loadLineShape(engine, refresh = true) {
9419 await engine.addShape("line", new LineDrawer(), refresh);
9420}
9421;// CONCATENATED MODULE: ../../move/parallax/dist/esm/ParallaxMover.js
9422
9423class ParallaxMover {
9424 init() {}
9425 isEnabled(particle) {
9426 return !isSsr() && !particle.destroyed && particle.container.actualOptions.interactivity.events.onHover.parallax.enable;
9427 }
9428 move(particle) {
9429 const container = particle.container,
9430 options = container.actualOptions,
9431 parallaxOptions = options.interactivity.events.onHover.parallax;
9432 if (isSsr() || !parallaxOptions.enable) {
9433 return;
9434 }
9435 const parallaxForce = parallaxOptions.force,
9436 mousePos = container.interactivity.mouse.position;
9437 if (!mousePos) {
9438 return;
9439 }
9440 const canvasSize = container.canvas.size,
9441 canvasCenter = {
9442 x: canvasSize.width / 2,
9443 y: canvasSize.height / 2
9444 },
9445 parallaxSmooth = parallaxOptions.smooth,
9446 factor = particle.getRadius() / parallaxForce,
9447 centerDistance = {
9448 x: (mousePos.x - canvasCenter.x) * factor,
9449 y: (mousePos.y - canvasCenter.y) * factor
9450 },
9451 {
9452 offset
9453 } = particle;
9454 offset.x += (centerDistance.x - offset.x) / parallaxSmooth;
9455 offset.y += (centerDistance.y - offset.y) / parallaxSmooth;
9456 }
9457}
9458;// CONCATENATED MODULE: ../../move/parallax/dist/esm/index.js
9459
9460async function loadParallaxMover(engine, refresh = true) {
9461 await engine.addMover("parallax", () => new ParallaxMover(), refresh);
9462}
9463;// CONCATENATED MODULE: ../../interactions/particles/attract/dist/esm/Attractor.js
9464
9465class Attractor_Attractor extends ParticlesInteractorBase {
9466 constructor(container) {
9467 super(container);
9468 }
9469 clear() {}
9470 init() {}
9471 async interact(p1) {
9472 const container = this.container,
9473 distance = p1.retina.attractDistance ?? container.retina.attractDistance,
9474 pos1 = p1.getPosition(),
9475 query = container.particles.quadTree.queryCircle(pos1, distance);
9476 for (const p2 of query) {
9477 if (p1 === p2 || !p2.options.move.attract.enable || p2.destroyed || p2.spawning) {
9478 continue;
9479 }
9480 const pos2 = p2.getPosition(),
9481 {
9482 dx,
9483 dy
9484 } = getDistances(pos1, pos2),
9485 rotate = p1.options.move.attract.rotate,
9486 ax = dx / (rotate.x * 1000),
9487 ay = dy / (rotate.y * 1000),
9488 p1Factor = p2.size.value / p1.size.value,
9489 p2Factor = 1 / p1Factor;
9490 p1.velocity.x -= ax * p1Factor;
9491 p1.velocity.y -= ay * p1Factor;
9492 p2.velocity.x += ax * p2Factor;
9493 p2.velocity.y += ay * p2Factor;
9494 }
9495 }
9496 isEnabled(particle) {
9497 return particle.options.move.attract.enable;
9498 }
9499 reset() {}
9500}
9501;// CONCATENATED MODULE: ../../interactions/particles/attract/dist/esm/index.js
9502
9503async function loadParticlesAttractInteraction(engine, refresh = true) {
9504 await engine.addInteractor("particlesAttract", container => new Attractor_Attractor(container), refresh);
9505}
9506;// CONCATENATED MODULE: ../../interactions/particles/collisions/dist/esm/Absorb.js
9507
9508function updateAbsorb(p1, r1, p2, r2, delta, pixelRatio) {
9509 const factor = clamp(p1.options.collisions.absorb.speed * delta.factor / 10, 0, r2);
9510 p1.size.value += factor / 2;
9511 p2.size.value -= factor;
9512 if (r2 <= pixelRatio) {
9513 p2.size.value = 0;
9514 p2.destroy();
9515 }
9516}
9517function absorb(p1, p2, delta, pixelRatio) {
9518 const r1 = p1.getRadius(),
9519 r2 = p2.getRadius();
9520 if (r1 === undefined && r2 !== undefined) {
9521 p1.destroy();
9522 } else if (r1 !== undefined && r2 === undefined) {
9523 p2.destroy();
9524 } else if (r1 !== undefined && r2 !== undefined) {
9525 if (r1 >= r2) {
9526 updateAbsorb(p1, r1, p2, r2, delta, pixelRatio);
9527 } else {
9528 updateAbsorb(p2, r2, p1, r1, delta, pixelRatio);
9529 }
9530 }
9531}
9532;// CONCATENATED MODULE: ../../interactions/particles/collisions/dist/esm/Bounce.js
9533
9534const fixBounceSpeed = p => {
9535 if (p.collisionMaxSpeed === undefined) {
9536 p.collisionMaxSpeed = getRangeValue(p.options.collisions.maxSpeed);
9537 }
9538 if (p.velocity.length > p.collisionMaxSpeed) {
9539 p.velocity.length = p.collisionMaxSpeed;
9540 }
9541};
9542function bounce(p1, p2) {
9543 circleBounce(circleBounceDataFromParticle(p1), circleBounceDataFromParticle(p2));
9544 fixBounceSpeed(p1);
9545 fixBounceSpeed(p2);
9546}
9547;// CONCATENATED MODULE: ../../interactions/particles/collisions/dist/esm/Destroy.js
9548
9549function destroy(p1, p2) {
9550 if (!p1.unbreakable && !p2.unbreakable) {
9551 bounce(p1, p2);
9552 }
9553 if (p1.getRadius() === undefined && p2.getRadius() !== undefined) {
9554 p1.destroy();
9555 } else if (p1.getRadius() !== undefined && p2.getRadius() === undefined) {
9556 p2.destroy();
9557 } else if (p1.getRadius() !== undefined && p2.getRadius() !== undefined) {
9558 const deleteP = p1.getRadius() >= p2.getRadius() ? p2 : p1;
9559 deleteP.destroy();
9560 }
9561}
9562;// CONCATENATED MODULE: ../../interactions/particles/collisions/dist/esm/ResolveCollision.js
9563
9564
9565
9566function resolveCollision(p1, p2, delta, pixelRatio) {
9567 switch (p1.options.collisions.mode) {
9568 case "absorb":
9569 {
9570 absorb(p1, p2, delta, pixelRatio);
9571 break;
9572 }
9573 case "bounce":
9574 {
9575 bounce(p1, p2);
9576 break;
9577 }
9578 case "destroy":
9579 {
9580 destroy(p1, p2);
9581 break;
9582 }
9583 }
9584}
9585;// CONCATENATED MODULE: ../../interactions/particles/collisions/dist/esm/Collider.js
9586
9587
9588class Collider extends ParticlesInteractorBase {
9589 constructor(container) {
9590 super(container);
9591 }
9592 clear() {}
9593 init() {}
9594 async interact(p1, delta) {
9595 if (p1.destroyed || p1.spawning) {
9596 return;
9597 }
9598 const container = this.container,
9599 pos1 = p1.getPosition(),
9600 radius1 = p1.getRadius(),
9601 query = container.particles.quadTree.queryCircle(pos1, radius1 * 2);
9602 for (const p2 of query) {
9603 if (p1 === p2 || !p2.options.collisions.enable || p1.options.collisions.mode !== p2.options.collisions.mode || p2.destroyed || p2.spawning) {
9604 continue;
9605 }
9606 const pos2 = p2.getPosition(),
9607 radius2 = p2.getRadius();
9608 if (Math.abs(Math.round(pos1.z) - Math.round(pos2.z)) > radius1 + radius2) {
9609 continue;
9610 }
9611 const dist = getDistance(pos1, pos2),
9612 distP = radius1 + radius2;
9613 if (dist > distP) {
9614 continue;
9615 }
9616 resolveCollision(p1, p2, delta, container.retina.pixelRatio);
9617 }
9618 }
9619 isEnabled(particle) {
9620 return particle.options.collisions.enable;
9621 }
9622 reset() {}
9623}
9624;// CONCATENATED MODULE: ../../interactions/particles/collisions/dist/esm/index.js
9625
9626async function loadParticlesCollisionsInteraction(engine, refresh = true) {
9627 await engine.addInteractor("particlesCollisions", container => new Collider(container), refresh);
9628}
9629;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/CircleWarp.js
9630
9631class CircleWarp extends Circle {
9632 constructor(x, y, radius, canvasSize) {
9633 super(x, y, radius);
9634 this.canvasSize = canvasSize;
9635 this.canvasSize = {
9636 ...canvasSize
9637 };
9638 }
9639 contains(point) {
9640 const {
9641 width,
9642 height
9643 } = this.canvasSize;
9644 const {
9645 x,
9646 y
9647 } = point;
9648 return super.contains(point) || super.contains({
9649 x: x - width,
9650 y
9651 }) || super.contains({
9652 x: x - width,
9653 y: y - height
9654 }) || super.contains({
9655 x,
9656 y: y - height
9657 });
9658 }
9659 intersects(range) {
9660 if (super.intersects(range)) {
9661 return true;
9662 }
9663 const rect = range,
9664 circle = range,
9665 newPos = {
9666 x: range.position.x - this.canvasSize.width,
9667 y: range.position.y - this.canvasSize.height
9668 };
9669 if (circle.radius !== undefined) {
9670 const biggerCircle = new Circle(newPos.x, newPos.y, circle.radius * 2);
9671 return super.intersects(biggerCircle);
9672 } else if (rect.size !== undefined) {
9673 const rectSW = new Rectangle(newPos.x, newPos.y, rect.size.width * 2, rect.size.height * 2);
9674 return super.intersects(rectSW);
9675 }
9676 return false;
9677 }
9678}
9679;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/Options/Classes/LinksShadow.js
9680
9681class LinksShadow {
9682 constructor() {
9683 this.blur = 5;
9684 this.color = new OptionsColor();
9685 this.color.value = "#000";
9686 this.enable = false;
9687 }
9688 load(data) {
9689 if (!data) {
9690 return;
9691 }
9692 if (data.blur !== undefined) {
9693 this.blur = data.blur;
9694 }
9695 this.color = OptionsColor.create(this.color, data.color);
9696 if (data.enable !== undefined) {
9697 this.enable = data.enable;
9698 }
9699 }
9700}
9701;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/Options/Classes/LinksTriangle.js
9702
9703class LinksTriangle {
9704 constructor() {
9705 this.enable = false;
9706 this.frequency = 1;
9707 }
9708 load(data) {
9709 if (!data) {
9710 return;
9711 }
9712 if (data.color !== undefined) {
9713 this.color = OptionsColor.create(this.color, data.color);
9714 }
9715 if (data.enable !== undefined) {
9716 this.enable = data.enable;
9717 }
9718 if (data.frequency !== undefined) {
9719 this.frequency = data.frequency;
9720 }
9721 if (data.opacity !== undefined) {
9722 this.opacity = data.opacity;
9723 }
9724 }
9725}
9726;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/Options/Classes/Links.js
9727
9728
9729
9730class Links {
9731 constructor() {
9732 this.blink = false;
9733 this.color = new OptionsColor();
9734 this.color.value = "#fff";
9735 this.consent = false;
9736 this.distance = 100;
9737 this.enable = false;
9738 this.frequency = 1;
9739 this.opacity = 1;
9740 this.shadow = new LinksShadow();
9741 this.triangles = new LinksTriangle();
9742 this.width = 1;
9743 this.warp = false;
9744 }
9745 load(data) {
9746 if (!data) {
9747 return;
9748 }
9749 if (data.id !== undefined) {
9750 this.id = data.id;
9751 }
9752 if (data.blink !== undefined) {
9753 this.blink = data.blink;
9754 }
9755 this.color = OptionsColor.create(this.color, data.color);
9756 if (data.consent !== undefined) {
9757 this.consent = data.consent;
9758 }
9759 if (data.distance !== undefined) {
9760 this.distance = data.distance;
9761 }
9762 if (data.enable !== undefined) {
9763 this.enable = data.enable;
9764 }
9765 if (data.frequency !== undefined) {
9766 this.frequency = data.frequency;
9767 }
9768 if (data.opacity !== undefined) {
9769 this.opacity = data.opacity;
9770 }
9771 this.shadow.load(data.shadow);
9772 this.triangles.load(data.triangles);
9773 if (data.width !== undefined) {
9774 this.width = data.width;
9775 }
9776 if (data.warp !== undefined) {
9777 this.warp = data.warp;
9778 }
9779 }
9780}
9781;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/Linker.js
9782
9783
9784
9785function getLinkDistance(pos1, pos2, optDistance, canvasSize, warp) {
9786 const {
9787 dx,
9788 dy,
9789 distance
9790 } = getDistances(pos1, pos2);
9791 if (!warp || distance <= optDistance) {
9792 return distance;
9793 }
9794 const absDiffs = {
9795 x: Math.abs(dx),
9796 y: Math.abs(dy)
9797 },
9798 warpDistances = {
9799 x: Math.min(absDiffs.x, canvasSize.width - absDiffs.x),
9800 y: Math.min(absDiffs.y, canvasSize.height - absDiffs.y)
9801 };
9802 return Math.sqrt(warpDistances.x ** 2 + warpDistances.y ** 2);
9803}
9804class Linker extends ParticlesInteractorBase {
9805 constructor(container) {
9806 super(container);
9807 this._setColor = p1 => {
9808 if (!p1.options.links) {
9809 return;
9810 }
9811 const container = this.linkContainer,
9812 linksOptions = p1.options.links;
9813 let linkColor = linksOptions.id === undefined ? container.particles.linksColor : container.particles.linksColors.get(linksOptions.id);
9814 if (linkColor) {
9815 return;
9816 }
9817 const optColor = linksOptions.color;
9818 linkColor = getLinkRandomColor(optColor, linksOptions.blink, linksOptions.consent);
9819 if (linksOptions.id === undefined) {
9820 container.particles.linksColor = linkColor;
9821 } else {
9822 container.particles.linksColors.set(linksOptions.id, linkColor);
9823 }
9824 };
9825 this.linkContainer = container;
9826 }
9827 clear() {}
9828 init() {
9829 this.linkContainer.particles.linksColor = undefined;
9830 this.linkContainer.particles.linksColors = new Map();
9831 }
9832 async interact(p1) {
9833 if (!p1.options.links) {
9834 return;
9835 }
9836 p1.links = [];
9837 const pos1 = p1.getPosition(),
9838 container = this.container,
9839 canvasSize = container.canvas.size;
9840 if (pos1.x < 0 || pos1.y < 0 || pos1.x > canvasSize.width || pos1.y > canvasSize.height) {
9841 return;
9842 }
9843 const linkOpt1 = p1.options.links,
9844 optOpacity = linkOpt1.opacity,
9845 optDistance = p1.retina.linksDistance ?? 0,
9846 warp = linkOpt1.warp,
9847 range = warp ? new CircleWarp(pos1.x, pos1.y, optDistance, canvasSize) : new Circle(pos1.x, pos1.y, optDistance),
9848 query = container.particles.quadTree.query(range);
9849 for (const p2 of query) {
9850 const linkOpt2 = p2.options.links;
9851 if (p1 === p2 || !linkOpt2?.enable || linkOpt1.id !== linkOpt2.id || p2.spawning || p2.destroyed || !p2.links || p1.links.some(t => t.destination === p2) || p2.links.some(t => t.destination === p1)) {
9852 continue;
9853 }
9854 const pos2 = p2.getPosition();
9855 if (pos2.x < 0 || pos2.y < 0 || pos2.x > canvasSize.width || pos2.y > canvasSize.height) {
9856 continue;
9857 }
9858 const distance = getLinkDistance(pos1, pos2, optDistance, canvasSize, warp && linkOpt2.warp);
9859 if (distance > optDistance) {
9860 continue;
9861 }
9862 const opacityLine = (1 - distance / optDistance) * optOpacity;
9863 this._setColor(p1);
9864 p1.links.push({
9865 destination: p2,
9866 opacity: opacityLine
9867 });
9868 }
9869 }
9870 isEnabled(particle) {
9871 return !!particle.options.links?.enable;
9872 }
9873 loadParticlesOptions(options, ...sources) {
9874 if (!options.links) {
9875 options.links = new Links();
9876 }
9877 for (const source of sources) {
9878 options.links.load(source?.links ?? source?.lineLinked ?? source?.line_linked);
9879 }
9880 }
9881 reset() {}
9882}
9883;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/interaction.js
9884
9885async function loadLinksInteraction(engine, refresh = true) {
9886 await engine.addInteractor("particlesLinks", container => new Linker(container), refresh);
9887}
9888;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/Utils.js
9889
9890function drawLinkLine(params) {
9891 let drawn = false;
9892 const {
9893 begin,
9894 end,
9895 maxDistance,
9896 context,
9897 canvasSize,
9898 width,
9899 backgroundMask,
9900 colorLine,
9901 opacity,
9902 links
9903 } = params;
9904 if (getDistance(begin, end) <= maxDistance) {
9905 drawLine(context, begin, end);
9906 drawn = true;
9907 } else if (links.warp) {
9908 let pi1;
9909 let pi2;
9910 const endNE = {
9911 x: end.x - canvasSize.width,
9912 y: end.y
9913 };
9914 const d1 = getDistances(begin, endNE);
9915 if (d1.distance <= maxDistance) {
9916 const yi = begin.y - d1.dy / d1.dx * begin.x;
9917 pi1 = {
9918 x: 0,
9919 y: yi
9920 };
9921 pi2 = {
9922 x: canvasSize.width,
9923 y: yi
9924 };
9925 } else {
9926 const endSW = {
9927 x: end.x,
9928 y: end.y - canvasSize.height
9929 };
9930 const d2 = getDistances(begin, endSW);
9931 if (d2.distance <= maxDistance) {
9932 const yi = begin.y - d2.dy / d2.dx * begin.x;
9933 const xi = -yi / (d2.dy / d2.dx);
9934 pi1 = {
9935 x: xi,
9936 y: 0
9937 };
9938 pi2 = {
9939 x: xi,
9940 y: canvasSize.height
9941 };
9942 } else {
9943 const endSE = {
9944 x: end.x - canvasSize.width,
9945 y: end.y - canvasSize.height
9946 };
9947 const d3 = getDistances(begin, endSE);
9948 if (d3.distance <= maxDistance) {
9949 const yi = begin.y - d3.dy / d3.dx * begin.x;
9950 const xi = -yi / (d3.dy / d3.dx);
9951 pi1 = {
9952 x: xi,
9953 y: yi
9954 };
9955 pi2 = {
9956 x: pi1.x + canvasSize.width,
9957 y: pi1.y + canvasSize.height
9958 };
9959 }
9960 }
9961 }
9962 if (pi1 && pi2) {
9963 drawLine(context, begin, pi1);
9964 drawLine(context, end, pi2);
9965 drawn = true;
9966 }
9967 }
9968 if (!drawn) {
9969 return;
9970 }
9971 context.lineWidth = width;
9972 if (backgroundMask.enable) {
9973 context.globalCompositeOperation = backgroundMask.composite;
9974 }
9975 context.strokeStyle = getStyleFromRgb(colorLine, opacity);
9976 const {
9977 shadow
9978 } = links;
9979 if (shadow.enable) {
9980 const shadowColor = rangeColorToRgb(shadow.color);
9981 if (shadowColor) {
9982 context.shadowBlur = shadow.blur;
9983 context.shadowColor = getStyleFromRgb(shadowColor);
9984 }
9985 }
9986 context.stroke();
9987}
9988function drawLinkTriangle(params) {
9989 const {
9990 context,
9991 pos1,
9992 pos2,
9993 pos3,
9994 backgroundMask,
9995 colorTriangle,
9996 opacityTriangle
9997 } = params;
9998 drawTriangle(context, pos1, pos2, pos3);
9999 if (backgroundMask.enable) {
10000 context.globalCompositeOperation = backgroundMask.composite;
10001 }
10002 context.fillStyle = getStyleFromRgb(colorTriangle, opacityTriangle);
10003 context.fill();
10004}
10005function getLinkKey(ids) {
10006 ids.sort((a, b) => a - b);
10007 return ids.join("_");
10008}
10009function setLinkFrequency(particles, dictionary) {
10010 const key = getLinkKey(particles.map(t => t.id));
10011 let res = dictionary.get(key);
10012 if (res === undefined) {
10013 res = getRandom();
10014 dictionary.set(key, res);
10015 }
10016 return res;
10017}
10018;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/LinkInstance.js
10019
10020
10021class LinkInstance {
10022 constructor(container) {
10023 this.container = container;
10024 this._drawLinkLine = (p1, link) => {
10025 const p1LinksOptions = p1.options.links;
10026 if (!p1LinksOptions?.enable) {
10027 return;
10028 }
10029 const container = this.container,
10030 options = container.actualOptions,
10031 p2 = link.destination,
10032 pos1 = p1.getPosition(),
10033 pos2 = p2.getPosition();
10034 let opacity = link.opacity;
10035 container.canvas.draw(ctx => {
10036 let colorLine;
10037 const twinkle = p1.options.twinkle?.lines;
10038 if (twinkle?.enable) {
10039 const twinkleFreq = twinkle.frequency,
10040 twinkleRgb = rangeColorToRgb(twinkle.color),
10041 twinkling = getRandom() < twinkleFreq;
10042 if (twinkling && twinkleRgb) {
10043 colorLine = twinkleRgb;
10044 opacity = getRangeValue(twinkle.opacity);
10045 }
10046 }
10047 if (!colorLine) {
10048 const linkColor = p1LinksOptions.id !== undefined ? container.particles.linksColors.get(p1LinksOptions.id) : container.particles.linksColor;
10049 colorLine = getLinkColor(p1, p2, linkColor);
10050 }
10051 if (!colorLine) {
10052 return;
10053 }
10054 const width = p1.retina.linksWidth ?? 0,
10055 maxDistance = p1.retina.linksDistance ?? 0,
10056 {
10057 backgroundMask
10058 } = options;
10059 drawLinkLine({
10060 context: ctx,
10061 width,
10062 begin: pos1,
10063 end: pos2,
10064 maxDistance,
10065 canvasSize: container.canvas.size,
10066 links: p1LinksOptions,
10067 backgroundMask: backgroundMask,
10068 colorLine,
10069 opacity
10070 });
10071 });
10072 };
10073 this._drawLinkTriangle = (p1, link1, link2) => {
10074 const linksOptions = p1.options.links;
10075 if (!linksOptions?.enable) {
10076 return;
10077 }
10078 const triangleOptions = linksOptions.triangles;
10079 if (!triangleOptions.enable) {
10080 return;
10081 }
10082 const container = this.container,
10083 options = container.actualOptions,
10084 p2 = link1.destination,
10085 p3 = link2.destination,
10086 opacityTriangle = triangleOptions.opacity ?? (link1.opacity + link2.opacity) / 2;
10087 if (opacityTriangle <= 0) {
10088 return;
10089 }
10090 container.canvas.draw(ctx => {
10091 const pos1 = p1.getPosition(),
10092 pos2 = p2.getPosition(),
10093 pos3 = p3.getPosition(),
10094 linksDistance = p1.retina.linksDistance ?? 0;
10095 if (getDistance(pos1, pos2) > linksDistance || getDistance(pos3, pos2) > linksDistance || getDistance(pos3, pos1) > linksDistance) {
10096 return;
10097 }
10098 let colorTriangle = rangeColorToRgb(triangleOptions.color);
10099 if (!colorTriangle) {
10100 const linkColor = linksOptions.id !== undefined ? container.particles.linksColors.get(linksOptions.id) : container.particles.linksColor;
10101 colorTriangle = getLinkColor(p1, p2, linkColor);
10102 }
10103 if (!colorTriangle) {
10104 return;
10105 }
10106 drawLinkTriangle({
10107 context: ctx,
10108 pos1,
10109 pos2,
10110 pos3,
10111 backgroundMask: options.backgroundMask,
10112 colorTriangle,
10113 opacityTriangle
10114 });
10115 });
10116 };
10117 this._drawTriangles = (options, p1, link, p1Links) => {
10118 const p2 = link.destination;
10119 if (!(options.links?.triangles.enable && p2.options.links?.triangles.enable)) {
10120 return;
10121 }
10122 const vertices = p2.links?.filter(t => {
10123 const linkFreq = this._getLinkFrequency(p2, t.destination);
10124 return p2.options.links && linkFreq <= p2.options.links.frequency && p1Links.findIndex(l => l.destination === t.destination) >= 0;
10125 });
10126 if (!vertices?.length) {
10127 return;
10128 }
10129 for (const vertex of vertices) {
10130 const p3 = vertex.destination,
10131 triangleFreq = this._getTriangleFrequency(p1, p2, p3);
10132 if (triangleFreq > options.links.triangles.frequency) {
10133 continue;
10134 }
10135 this._drawLinkTriangle(p1, link, vertex);
10136 }
10137 };
10138 this._getLinkFrequency = (p1, p2) => {
10139 return setLinkFrequency([p1, p2], this._freqs.links);
10140 };
10141 this._getTriangleFrequency = (p1, p2, p3) => {
10142 return setLinkFrequency([p1, p2, p3], this._freqs.triangles);
10143 };
10144 this._freqs = {
10145 links: new Map(),
10146 triangles: new Map()
10147 };
10148 }
10149 drawParticle(context, particle) {
10150 const {
10151 links,
10152 options
10153 } = particle;
10154 if (!links || links.length <= 0) {
10155 return;
10156 }
10157 const p1Links = links.filter(l => options.links && this._getLinkFrequency(particle, l.destination) <= options.links.frequency);
10158 for (const link of p1Links) {
10159 this._drawTriangles(options, particle, link, p1Links);
10160 if (link.opacity > 0 && (particle.retina.linksWidth ?? 0) > 0) {
10161 this._drawLinkLine(particle, link);
10162 }
10163 }
10164 }
10165 async init() {
10166 this._freqs.links = new Map();
10167 this._freqs.triangles = new Map();
10168 }
10169 particleCreated(particle) {
10170 particle.links = [];
10171 if (!particle.options.links) {
10172 return;
10173 }
10174 const ratio = this.container.retina.pixelRatio,
10175 {
10176 retina
10177 } = particle,
10178 {
10179 distance,
10180 width
10181 } = particle.options.links;
10182 retina.linksDistance = distance * ratio;
10183 retina.linksWidth = width * ratio;
10184 }
10185 particleDestroyed(particle) {
10186 particle.links = [];
10187 }
10188}
10189;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/plugin.js
10190
10191class LinksPlugin {
10192 constructor() {
10193 this.id = "links";
10194 }
10195 getPlugin(container) {
10196 return new LinkInstance(container);
10197 }
10198 loadOptions() {}
10199 needsPlugin() {
10200 return true;
10201 }
10202}
10203async function loadLinksPlugin(engine, refresh = true) {
10204 const plugin = new LinksPlugin();
10205 await engine.addPlugin(plugin, refresh);
10206}
10207;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/index.js
10208
10209
10210async function loadParticlesLinksInteraction(engine, refresh = true) {
10211 await loadLinksInteraction(engine, refresh);
10212 await loadLinksPlugin(engine, refresh);
10213}
10214
10215
10216
10217
10218
10219
10220;// CONCATENATED MODULE: ../../shapes/polygon/dist/esm/PolygonDrawerBase.js
10221
10222class PolygonDrawerBase {
10223 draw(context, particle, radius) {
10224 const start = this.getCenter(particle, radius),
10225 side = this.getSidesData(particle, radius),
10226 sideCount = side.count.numerator * side.count.denominator,
10227 decimalSides = side.count.numerator / side.count.denominator,
10228 interiorAngleDegrees = 180 * (decimalSides - 2) / decimalSides,
10229 interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180;
10230 if (!context) {
10231 return;
10232 }
10233 context.beginPath();
10234 context.translate(start.x, start.y);
10235 context.moveTo(0, 0);
10236 for (let i = 0; i < sideCount; i++) {
10237 context.lineTo(side.length, 0);
10238 context.translate(side.length, 0);
10239 context.rotate(interiorAngle);
10240 }
10241 }
10242 getSidesCount(particle) {
10243 const polygon = particle.shapeData;
10244 return Math.round(getRangeValue(polygon?.sides ?? polygon?.nb_sides ?? 5));
10245 }
10246}
10247;// CONCATENATED MODULE: ../../shapes/polygon/dist/esm/PolygonDrawer.js
10248
10249class PolygonDrawer extends PolygonDrawerBase {
10250 getCenter(particle, radius) {
10251 return {
10252 x: -radius / (particle.sides / 3.5),
10253 y: -radius / (2.66 / 3.5)
10254 };
10255 }
10256 getSidesData(particle, radius) {
10257 const sides = particle.sides;
10258 return {
10259 count: {
10260 denominator: 1,
10261 numerator: sides
10262 },
10263 length: radius * 2.66 / (sides / 3)
10264 };
10265 }
10266}
10267;// CONCATENATED MODULE: ../../shapes/polygon/dist/esm/TriangleDrawer.js
10268
10269class TriangleDrawer extends PolygonDrawerBase {
10270 getCenter(particle, radius) {
10271 return {
10272 x: -radius,
10273 y: radius / 1.66
10274 };
10275 }
10276 getSidesCount() {
10277 return 3;
10278 }
10279 getSidesData(particle, radius) {
10280 return {
10281 count: {
10282 denominator: 2,
10283 numerator: 3
10284 },
10285 length: radius * 2
10286 };
10287 }
10288}
10289;// CONCATENATED MODULE: ../../shapes/polygon/dist/esm/index.js
10290
10291
10292async function loadGenericPolygonShape(engine, refresh = true) {
10293 await engine.addShape("polygon", new PolygonDrawer(), refresh);
10294}
10295async function loadTriangleShape(engine, refresh = true) {
10296 await engine.addShape("triangle", new TriangleDrawer(), refresh);
10297}
10298async function loadPolygonShape(engine, refresh = true) {
10299 await loadGenericPolygonShape(engine, refresh);
10300 await loadTriangleShape(engine, refresh);
10301}
10302;// CONCATENATED MODULE: ../../updaters/rotate/dist/esm/Options/Classes/RotateAnimation.js
10303
10304class RotateAnimation {
10305 constructor() {
10306 this.enable = false;
10307 this.speed = 0;
10308 this.decay = 0;
10309 this.sync = false;
10310 }
10311 load(data) {
10312 if (!data) {
10313 return;
10314 }
10315 if (data.enable !== undefined) {
10316 this.enable = data.enable;
10317 }
10318 if (data.speed !== undefined) {
10319 this.speed = setRangeValue(data.speed);
10320 }
10321 if (data.decay !== undefined) {
10322 this.decay = setRangeValue(data.decay);
10323 }
10324 if (data.sync !== undefined) {
10325 this.sync = data.sync;
10326 }
10327 }
10328}
10329;// CONCATENATED MODULE: ../../updaters/rotate/dist/esm/Options/Classes/Rotate.js
10330
10331
10332class Rotate extends ValueWithRandom {
10333 constructor() {
10334 super();
10335 this.animation = new RotateAnimation();
10336 this.direction = "clockwise";
10337 this.path = false;
10338 this.value = 0;
10339 }
10340 load(data) {
10341 if (!data) {
10342 return;
10343 }
10344 super.load(data);
10345 if (data.direction !== undefined) {
10346 this.direction = data.direction;
10347 }
10348 this.animation.load(data.animation);
10349 if (data.path !== undefined) {
10350 this.path = data.path;
10351 }
10352 }
10353}
10354;// CONCATENATED MODULE: ../../updaters/rotate/dist/esm/RotateUpdater.js
10355
10356
10357function updateRotate(particle, delta) {
10358 const rotate = particle.rotate,
10359 rotateOptions = particle.options.rotate;
10360 if (!rotate || !rotateOptions) {
10361 return;
10362 }
10363 const rotateAnimation = rotateOptions.animation,
10364 speed = (rotate.velocity ?? 0) * delta.factor,
10365 max = 2 * Math.PI,
10366 decay = rotate.decay ?? 1;
10367 if (!rotateAnimation.enable) {
10368 return;
10369 }
10370 switch (rotate.status) {
10371 case "increasing":
10372 rotate.value += speed;
10373 if (rotate.value > max) {
10374 rotate.value -= max;
10375 }
10376 break;
10377 case "decreasing":
10378 default:
10379 rotate.value -= speed;
10380 if (rotate.value < 0) {
10381 rotate.value += max;
10382 }
10383 break;
10384 }
10385 if (rotate.velocity && decay !== 1) {
10386 rotate.velocity *= decay;
10387 }
10388}
10389class RotateUpdater {
10390 constructor(container) {
10391 this.container = container;
10392 }
10393 init(particle) {
10394 const rotateOptions = particle.options.rotate;
10395 if (!rotateOptions) {
10396 return;
10397 }
10398 particle.rotate = {
10399 enable: rotateOptions.animation.enable,
10400 value: getRangeValue(rotateOptions.value) * Math.PI / 180
10401 };
10402 particle.pathRotation = rotateOptions.path;
10403 let rotateDirection = rotateOptions.direction;
10404 if (rotateDirection === "random") {
10405 const index = Math.floor(getRandom() * 2);
10406 rotateDirection = index > 0 ? "counter-clockwise" : "clockwise";
10407 }
10408 switch (rotateDirection) {
10409 case "counter-clockwise":
10410 case "counterClockwise":
10411 particle.rotate.status = "decreasing";
10412 break;
10413 case "clockwise":
10414 particle.rotate.status = "increasing";
10415 break;
10416 }
10417 const rotateAnimation = rotateOptions.animation;
10418 if (rotateAnimation.enable) {
10419 particle.rotate.decay = 1 - getRangeValue(rotateAnimation.decay);
10420 particle.rotate.velocity = getRangeValue(rotateAnimation.speed) / 360 * this.container.retina.reduceFactor;
10421 if (!rotateAnimation.sync) {
10422 particle.rotate.velocity *= getRandom();
10423 }
10424 }
10425 particle.rotation = particle.rotate.value;
10426 }
10427 isEnabled(particle) {
10428 const rotate = particle.options.rotate;
10429 if (!rotate) {
10430 return false;
10431 }
10432 return !particle.destroyed && !particle.spawning && rotate.animation.enable && !rotate.path;
10433 }
10434 loadOptions(options, ...sources) {
10435 if (!options.rotate) {
10436 options.rotate = new Rotate();
10437 }
10438 for (const source of sources) {
10439 options.rotate.load(source?.rotate);
10440 }
10441 }
10442 update(particle, delta) {
10443 if (!this.isEnabled(particle)) {
10444 return;
10445 }
10446 updateRotate(particle, delta);
10447 particle.rotation = particle.rotate?.value ?? 0;
10448 }
10449}
10450;// CONCATENATED MODULE: ../../updaters/rotate/dist/esm/index.js
10451
10452async function loadRotateUpdater(engine, refresh = true) {
10453 await engine.addParticleUpdater("rotate", container => new RotateUpdater(container), refresh);
10454}
10455;// CONCATENATED MODULE: ../../shapes/square/dist/esm/SquareDrawer.js
10456const fixFactor = Math.sqrt(2);
10457class SquareDrawer {
10458 draw(context, particle, radius) {
10459 const fixedRadius = radius / fixFactor,
10460 fixedDiameter = fixedRadius * 2;
10461 context.rect(-fixedRadius, -fixedRadius, fixedDiameter, fixedDiameter);
10462 }
10463 getSidesCount() {
10464 return 4;
10465 }
10466}
10467;// CONCATENATED MODULE: ../../shapes/square/dist/esm/index.js
10468
10469async function loadSquareShape(engine, refresh = true) {
10470 await engine.addShape(["edge", "square"], new SquareDrawer(), refresh);
10471}
10472;// CONCATENATED MODULE: ../../shapes/star/dist/esm/StarDrawer.js
10473
10474class StarDrawer {
10475 draw(context, particle, radius) {
10476 const sides = particle.sides,
10477 inset = particle.starInset ?? 2;
10478 context.moveTo(0, 0 - radius);
10479 for (let i = 0; i < sides; i++) {
10480 context.rotate(Math.PI / sides);
10481 context.lineTo(0, 0 - radius * inset);
10482 context.rotate(Math.PI / sides);
10483 context.lineTo(0, 0 - radius);
10484 }
10485 }
10486 getSidesCount(particle) {
10487 const star = particle.shapeData;
10488 return Math.round(getRangeValue(star?.sides ?? star?.nb_sides ?? 5));
10489 }
10490 particleInit(container, particle) {
10491 const star = particle.shapeData,
10492 inset = getRangeValue(star?.inset ?? 2);
10493 particle.starInset = inset;
10494 }
10495}
10496;// CONCATENATED MODULE: ../../shapes/star/dist/esm/index.js
10497
10498async function loadStarShape(engine, refresh = true) {
10499 await engine.addShape("star", new StarDrawer(), refresh);
10500}
10501;// CONCATENATED MODULE: ../../updaters/strokeColor/dist/esm/Utils.js
10502
10503function Utils_updateColorValue(delta, colorValue, valueAnimation, max, decrease) {
10504 if (!colorValue || !valueAnimation.enable || (colorValue.maxLoops ?? 0) > 0 && (colorValue.loops ?? 0) > (colorValue.maxLoops ?? 0)) {
10505 return;
10506 }
10507 if (!colorValue.time) {
10508 colorValue.time = 0;
10509 }
10510 if ((colorValue.delayTime ?? 0) > 0 && colorValue.time < (colorValue.delayTime ?? 0)) {
10511 colorValue.time += delta.value;
10512 }
10513 if ((colorValue.delayTime ?? 0) > 0 && colorValue.time < (colorValue.delayTime ?? 0)) {
10514 return;
10515 }
10516 const offset = randomInRange(valueAnimation.offset),
10517 velocity = (colorValue.velocity ?? 0) * delta.factor + offset * 3.6,
10518 decay = colorValue.decay ?? 1;
10519 if (!decrease || colorValue.status === "increasing") {
10520 colorValue.value += velocity;
10521 if (colorValue.value > max) {
10522 if (!colorValue.loops) {
10523 colorValue.loops = 0;
10524 }
10525 colorValue.loops++;
10526 if (decrease) {
10527 colorValue.status = "decreasing";
10528 colorValue.value -= colorValue.value % max;
10529 }
10530 }
10531 } else {
10532 colorValue.value -= velocity;
10533 if (colorValue.value < 0) {
10534 if (!colorValue.loops) {
10535 colorValue.loops = 0;
10536 }
10537 colorValue.loops++;
10538 colorValue.status = "increasing";
10539 colorValue.value += colorValue.value;
10540 }
10541 }
10542 if (colorValue.velocity && decay !== 1) {
10543 colorValue.velocity *= decay;
10544 }
10545 if (colorValue.value > max) {
10546 colorValue.value %= max;
10547 }
10548}
10549function updateStrokeColor(particle, delta) {
10550 if (!particle.strokeColor || !particle.strokeAnimation) {
10551 return;
10552 }
10553 const {
10554 h,
10555 s,
10556 l
10557 } = particle.strokeColor,
10558 {
10559 h: hAnimation,
10560 s: sAnimation,
10561 l: lAnimation
10562 } = particle.strokeAnimation;
10563 if (h) {
10564 Utils_updateColorValue(delta, h, hAnimation, 360, false);
10565 }
10566 if (s) {
10567 Utils_updateColorValue(delta, s, sAnimation, 100, true);
10568 }
10569 if (l) {
10570 Utils_updateColorValue(delta, l, lAnimation, 100, true);
10571 }
10572}
10573;// CONCATENATED MODULE: ../../updaters/strokeColor/dist/esm/StrokeColorUpdater.js
10574
10575
10576class StrokeColorUpdater {
10577 constructor(container) {
10578 this.container = container;
10579 }
10580 init(particle) {
10581 const container = this.container,
10582 options = particle.options;
10583 const stroke = itemFromSingleOrMultiple(options.stroke, particle.id, options.reduceDuplicates);
10584 particle.strokeWidth = getRangeValue(stroke.width) * container.retina.pixelRatio;
10585 particle.strokeOpacity = getRangeValue(stroke.opacity ?? 1);
10586 particle.strokeAnimation = stroke.color?.animation;
10587 const strokeHslColor = rangeColorToHsl(stroke.color) ?? particle.getFillColor();
10588 if (strokeHslColor) {
10589 particle.strokeColor = getHslAnimationFromHsl(strokeHslColor, particle.strokeAnimation, container.retina.reduceFactor);
10590 }
10591 }
10592 isEnabled(particle) {
10593 const color = particle.strokeAnimation,
10594 {
10595 strokeColor
10596 } = particle;
10597 return !particle.destroyed && !particle.spawning && !!color && (strokeColor?.h.value !== undefined && strokeColor.h.enable || strokeColor?.s.value !== undefined && strokeColor.s.enable || strokeColor?.l.value !== undefined && strokeColor.l.enable);
10598 }
10599 update(particle, delta) {
10600 if (!this.isEnabled(particle)) {
10601 return;
10602 }
10603 updateStrokeColor(particle, delta);
10604 }
10605}
10606;// CONCATENATED MODULE: ../../updaters/strokeColor/dist/esm/index.js
10607
10608async function loadStrokeColorUpdater(engine, refresh = true) {
10609 await engine.addParticleUpdater("strokeColor", container => new StrokeColorUpdater(container), refresh);
10610}
10611;// CONCATENATED MODULE: ../../shapes/text/dist/esm/TextDrawer.js
10612
10613const validTypes = ["text", "character", "char"];
10614class TextDrawer {
10615 draw(context, particle, radius, opacity) {
10616 const character = particle.shapeData;
10617 if (character === undefined) {
10618 return;
10619 }
10620 const textData = character.value;
10621 if (textData === undefined) {
10622 return;
10623 }
10624 if (particle.text === undefined) {
10625 particle.text = itemFromSingleOrMultiple(textData, particle.randomIndexData);
10626 }
10627 const text = particle.text,
10628 style = character.style ?? "",
10629 weight = character.weight ?? "400",
10630 size = Math.round(radius) * 2,
10631 font = character.font ?? "Verdana",
10632 fill = particle.fill,
10633 offsetX = text.length * radius / 2;
10634 context.font = `${style} ${weight} ${size}px "${font}"`;
10635 const pos = {
10636 x: -offsetX,
10637 y: radius / 2
10638 };
10639 context.globalAlpha = opacity;
10640 if (fill) {
10641 context.fillText(text, pos.x, pos.y);
10642 } else {
10643 context.strokeText(text, pos.x, pos.y);
10644 }
10645 context.globalAlpha = 1;
10646 }
10647 getSidesCount() {
10648 return 12;
10649 }
10650 async init(container) {
10651 const options = container.actualOptions;
10652 if (validTypes.find(t => isInArray(t, options.particles.shape.type))) {
10653 const shapeOptions = validTypes.map(t => options.particles.shape.options[t]).find(t => !!t),
10654 promises = [];
10655 executeOnSingleOrMultiple(shapeOptions, shape => {
10656 promises.push(loadFont(shape.font, shape.weight));
10657 });
10658 await Promise.all(promises);
10659 }
10660 }
10661 particleInit(container, particle) {
10662 if (!particle.shape || !validTypes.includes(particle.shape)) {
10663 return;
10664 }
10665 const character = particle.shapeData;
10666 if (character === undefined) {
10667 return;
10668 }
10669 const textData = character.value;
10670 if (textData === undefined) {
10671 return;
10672 }
10673 particle.text = itemFromSingleOrMultiple(textData, particle.randomIndexData);
10674 }
10675}
10676;// CONCATENATED MODULE: ../../shapes/text/dist/esm/index.js
10677
10678async function loadTextShape(engine, refresh = true) {
10679 await engine.addShape(validTypes, new TextDrawer(), refresh);
10680}
10681;// CONCATENATED MODULE: ./dist/browser/index.js
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708async function loadSlim(engine, refresh = true) {
10709 initPjs(engine);
10710 await loadParallaxMover(engine, false);
10711 await loadExternalAttractInteraction(engine, false);
10712 await loadExternalBounceInteraction(engine, false);
10713 await loadExternalBubbleInteraction(engine, false);
10714 await loadExternalConnectInteraction(engine, false);
10715 await loadExternalGrabInteraction(engine, false);
10716 await loadExternalPauseInteraction(engine, false);
10717 await loadExternalPushInteraction(engine, false);
10718 await loadExternalRemoveInteraction(engine, false);
10719 await loadExternalRepulseInteraction(engine, false);
10720 await loadExternalSlowInteraction(engine, false);
10721 await loadParticlesAttractInteraction(engine, false);
10722 await loadParticlesCollisionsInteraction(engine, false);
10723 await loadParticlesLinksInteraction(engine, false);
10724 await loadEasingQuadPlugin();
10725 await loadImageShape(engine, false);
10726 await loadLineShape(engine, false);
10727 await loadPolygonShape(engine, false);
10728 await loadSquareShape(engine, false);
10729 await loadStarShape(engine, false);
10730 await loadTextShape(engine, false);
10731 await loadLifeUpdater(engine, false);
10732 await loadRotateUpdater(engine, false);
10733 await loadStrokeColorUpdater(engine, false);
10734 await loadBasic(engine, refresh);
10735}
10736;// CONCATENATED MODULE: ./dist/browser/bundle.js
10737
10738
10739loadSlim(tsParticles);
10740
10741
10742/******/ return __webpack_exports__;
10743/******/ })()
10744;
10745});
\No newline at end of file