tsparticles 2.3.2 → 2.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v2.3.2
7
+ * v2.3.4
8
8
  */
9
9
  (function webpackUniversalModuleDefinition(root, factory) {
10
10
  if(typeof exports === 'object' && typeof module === 'object')
@@ -20,7 +20,7 @@ return /******/ (() => { // webpackBootstrap
20
20
  /******/ "use strict";
21
21
  /******/ var __webpack_modules__ = ({
22
22
 
23
- /***/ 417:
23
+ /***/ 74:
24
24
  /***/ (() => {
25
25
 
26
26
 
@@ -1898,8 +1898,6 @@ __webpack_require__.d(__webpack_exports__, {
1898
1898
  "Rectangle": () => (/* reexport */ Rectangle),
1899
1899
  "Responsive": () => (/* reexport */ Responsive),
1900
1900
  "RgbColorManager": () => (/* reexport */ RgbColorManager),
1901
- "Rotate": () => (/* reexport */ Rotate),
1902
- "RotateAnimation": () => (/* reexport */ RotateAnimation),
1903
1901
  "Shadow": () => (/* reexport */ Shadow),
1904
1902
  "Shape": () => (/* reexport */ Shape),
1905
1903
  "Size": () => (/* reexport */ Size),
@@ -1962,6 +1960,7 @@ __webpack_require__.d(__webpack_exports__, {
1962
1960
  "getStyleFromHsl": () => (/* reexport */ getStyleFromHsl),
1963
1961
  "getStyleFromRgb": () => (/* reexport */ getStyleFromRgb),
1964
1962
  "getValue": () => (/* reexport */ getValue),
1963
+ "hasMatchMedia": () => (/* reexport */ hasMatchMedia),
1965
1964
  "hslToRgb": () => (/* reexport */ hslToRgb),
1966
1965
  "hslaToRgba": () => (/* reexport */ hslaToRgba),
1967
1966
  "isDivModeEnabled": () => (/* reexport */ isDivModeEnabled),
@@ -1989,6 +1988,7 @@ __webpack_require__.d(__webpack_exports__, {
1989
1988
  "rectBounce": () => (/* reexport */ rectBounce),
1990
1989
  "resizeEvent": () => (/* reexport */ resizeEvent),
1991
1990
  "rgbToHsl": () => (/* reexport */ rgbToHsl),
1991
+ "safeMatchMedia": () => (/* reexport */ safeMatchMedia),
1992
1992
  "setRandom": () => (/* reexport */ setRandom),
1993
1993
  "setRangeValue": () => (/* reexport */ setRangeValue),
1994
1994
  "singleDivModeExecute": () => (/* reexport */ singleDivModeExecute),
@@ -2489,6 +2489,16 @@ function checkSelector(element, selectors) {
2489
2489
  function isSsr() {
2490
2490
  return typeof window === "undefined" || !window || typeof window.document === "undefined" || !window.document;
2491
2491
  }
2492
+ function hasMatchMedia() {
2493
+ return !isSsr() && typeof matchMedia !== "undefined";
2494
+ }
2495
+ function safeMatchMedia(query) {
2496
+ if (!hasMatchMedia()) {
2497
+ return;
2498
+ }
2499
+
2500
+ return matchMedia(query);
2501
+ }
2492
2502
  function animate() {
2493
2503
  return isSsr() ? callback => setTimeout(callback) : callback => (requestAnimationFrame || setTimeout)(callback);
2494
2504
  }
@@ -2507,8 +2517,7 @@ function arrayRandomIndex(array) {
2507
2517
  return Math.floor(getRandom() * array.length);
2508
2518
  }
2509
2519
  function itemFromArray(array, index, useIndex = true) {
2510
- const fixedIndex = index !== undefined && useIndex ? index % array.length : arrayRandomIndex(array);
2511
- return array[fixedIndex];
2520
+ return array[index !== undefined && useIndex ? index % array.length : arrayRandomIndex(array)];
2512
2521
  }
2513
2522
  function isPointInside(point, size, offset, radius, direction) {
2514
2523
  return areBoundsInside(calculateBounds(point, radius !== null && radius !== void 0 ? radius : 0), size, offset, direction);
@@ -2709,8 +2718,8 @@ function findItemFromSingleOrMultiple(obj, callback) {
2709
2718
  const randomColorValue = "random",
2710
2719
  midColorValue = "mid",
2711
2720
  colorManagers = new Map();
2712
- function addColorManager(key, manager) {
2713
- colorManagers.set(key, manager);
2721
+ function addColorManager(manager) {
2722
+ colorManagers.set(manager.key, manager);
2714
2723
  }
2715
2724
 
2716
2725
  function hue2rgb(p, q, t) {
@@ -2965,6 +2974,8 @@ function getLinkRandomColor(optColor, blink, consent) {
2965
2974
  return randomColorValue;
2966
2975
  }
2967
2976
 
2977
+ return midColorValue;
2978
+ } else if (color === midColorValue) {
2968
2979
  return midColorValue;
2969
2980
  } else {
2970
2981
  return rangeColorToRgb({
@@ -3070,7 +3081,7 @@ function drawParticle(data) {
3070
3081
  }
3071
3082
 
3072
3083
  context.beginPath();
3073
- const angle = particle.rotation + (particle.options.rotate.path ? particle.velocity.angle : 0);
3084
+ const angle = particle.rotation + (particle.pathRotation ? particle.velocity.angle : 0);
3074
3085
 
3075
3086
  if (angle !== 0) {
3076
3087
  context.rotate(angle);
@@ -3800,7 +3811,7 @@ class EventListeners {
3800
3811
  container.interactivity.element = container.canvas.element;
3801
3812
  }
3802
3813
 
3803
- const mediaMatch = !isSsr() && typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)");
3814
+ const mediaMatch = safeMatchMedia("(prefers-color-scheme: dark)");
3804
3815
 
3805
3816
  if (mediaMatch) {
3806
3817
  if (mediaMatch.addEventListener !== undefined) {
@@ -5455,70 +5466,6 @@ class ParticlesNumber {
5455
5466
  }
5456
5467
  }
5457
5468
 
5458
- }
5459
- ;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Rotate/RotateAnimation.js
5460
-
5461
- class RotateAnimation {
5462
- constructor() {
5463
- this.enable = false;
5464
- this.speed = 0;
5465
- this.decay = 0;
5466
- this.sync = false;
5467
- }
5468
-
5469
- load(data) {
5470
- if (!data) {
5471
- return;
5472
- }
5473
-
5474
- if (data.enable !== undefined) {
5475
- this.enable = data.enable;
5476
- }
5477
-
5478
- if (data.speed !== undefined) {
5479
- this.speed = setRangeValue(data.speed);
5480
- }
5481
-
5482
- if (data.decay !== undefined) {
5483
- this.decay = setRangeValue(data.decay);
5484
- }
5485
-
5486
- if (data.sync !== undefined) {
5487
- this.sync = data.sync;
5488
- }
5489
- }
5490
-
5491
- }
5492
- ;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Rotate/Rotate.js
5493
-
5494
-
5495
- class Rotate extends ValueWithRandom {
5496
- constructor() {
5497
- super();
5498
- this.animation = new RotateAnimation();
5499
- this.direction = "clockwise";
5500
- this.path = false;
5501
- this.value = 0;
5502
- }
5503
-
5504
- load(data) {
5505
- if (!data) {
5506
- return;
5507
- }
5508
-
5509
- super.load(data);
5510
-
5511
- if (data.direction !== undefined) {
5512
- this.direction = data.direction;
5513
- }
5514
-
5515
- this.animation.load(data.animation);
5516
-
5517
- if (data.path !== undefined) {
5518
- this.path = data.path;
5519
- }
5520
- }
5521
-
5522
5469
  }
5523
5470
  ;// CONCATENATED MODULE: ../../engine/dist/esm/Options/Classes/Particles/Shadow.js
5524
5471
 
@@ -5843,7 +5790,6 @@ class ZIndex extends ValueWithRandom {
5843
5790
 
5844
5791
 
5845
5792
 
5846
-
5847
5793
  class ParticlesOptions {
5848
5794
  constructor(engine, container) {
5849
5795
  this._engine = engine;
@@ -5857,7 +5803,6 @@ class ParticlesOptions {
5857
5803
  this.number = new ParticlesNumber();
5858
5804
  this.opacity = new Opacity();
5859
5805
  this.reduceDuplicates = false;
5860
- this.rotate = new Rotate();
5861
5806
  this.shadow = new Shadow();
5862
5807
  this.shape = new Shape();
5863
5808
  this.size = new Size();
@@ -5893,7 +5838,6 @@ class ParticlesOptions {
5893
5838
  this.reduceDuplicates = data.reduceDuplicates;
5894
5839
  }
5895
5840
 
5896
- this.rotate.load(data.rotate);
5897
5841
  this.shape.load(data.shape);
5898
5842
  this.size.load(data.size);
5899
5843
  this.shadow.load(data.shadow);
@@ -6135,7 +6079,7 @@ class Options {
6135
6079
  this.load(chosenTheme.options);
6136
6080
  }
6137
6081
  } else {
6138
- const mediaMatch = typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)"),
6082
+ const mediaMatch = safeMatchMedia("(prefers-color-scheme: dark)"),
6139
6083
  clientDarkMode = mediaMatch && mediaMatch.matches,
6140
6084
  defaultTheme = this._findDefaultTheme(clientDarkMode ? "dark" : "light");
6141
6085
 
@@ -6262,6 +6206,7 @@ class Particle {
6262
6206
  this.group = group;
6263
6207
  this._engine = engine;
6264
6208
  this.fill = true;
6209
+ this.pathRotation = false;
6265
6210
  this.close = true;
6266
6211
  this.lastPathTime = 0;
6267
6212
  this.destroyed = false;
@@ -6847,10 +6792,6 @@ class Particles {
6847
6792
  this.limit = 0;
6848
6793
  this.needsSort = false;
6849
6794
  this.lastZIndex = 0;
6850
- this.freqs = {
6851
- links: new Map(),
6852
- triangles: new Map()
6853
- };
6854
6795
  this.interactionManager = new InteractionManager(this._engine, container);
6855
6796
  const canvasSize = this.container.canvas.size;
6856
6797
  this.quadTree = new QuadTree(new Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, canvasSize.width * 3 / 2, canvasSize.height * 3 / 2), 4);
@@ -6924,45 +6865,6 @@ class Particles {
6924
6865
  }
6925
6866
  }
6926
6867
 
6927
- getLinkFrequency(p1, p2) {
6928
- const range = setRangeValue(p1.id, p2.id),
6929
- key = `${getRangeMin(range)}_${getRangeMax(range)}`;
6930
- let res = this.freqs.links.get(key);
6931
-
6932
- if (res === undefined) {
6933
- res = getRandom();
6934
- this.freqs.links.set(key, res);
6935
- }
6936
-
6937
- return res;
6938
- }
6939
-
6940
- getTriangleFrequency(p1, p2, p3) {
6941
- let [id1, id2, id3] = [p1.id, p2.id, p3.id];
6942
-
6943
- if (id1 > id2) {
6944
- [id2, id1] = [id1, id2];
6945
- }
6946
-
6947
- if (id2 > id3) {
6948
- [id3, id2] = [id2, id3];
6949
- }
6950
-
6951
- if (id1 > id3) {
6952
- [id3, id1] = [id1, id3];
6953
- }
6954
-
6955
- const key = `${id1}_${id2}_${id3}`;
6956
- let res = this.freqs.triangles.get(key);
6957
-
6958
- if (res === undefined) {
6959
- res = getRandom();
6960
- this.freqs.triangles.set(key, res);
6961
- }
6962
-
6963
- return res;
6964
- }
6965
-
6966
6868
  handleClickMode(mode) {
6967
6869
  this.interactionManager.handleClickMode(mode);
6968
6870
  }
@@ -6974,8 +6876,6 @@ class Particles {
6974
6876
  options = container.actualOptions;
6975
6877
  this.lastZIndex = 0;
6976
6878
  this.needsSort = false;
6977
- this.freqs.links = new Map();
6978
- this.freqs.triangles = new Map();
6979
6879
  let handled = false;
6980
6880
  this.updaters = this._engine.plugins.getUpdaters(container, true);
6981
6881
  this.interactionManager.init();
@@ -7037,7 +6937,7 @@ class Particles {
7037
6937
  }
7038
6938
 
7039
6939
  removeAt(index, quantity = 1, group, override) {
7040
- if (!(index >= 0 && index <= this.count)) {
6940
+ if (index < 0 || index > this.count) {
7041
6941
  return;
7042
6942
  }
7043
6943
 
@@ -7227,26 +7127,24 @@ class Retina {
7227
7127
  const motionOptions = this.container.actualOptions.motion;
7228
7128
 
7229
7129
  if (motionOptions && (motionOptions.disable || motionOptions.reduce.value)) {
7230
- if (isSsr() || typeof matchMedia === "undefined" || !matchMedia) {
7231
- this.reduceFactor = 1;
7232
- } else {
7233
- const mediaQuery = matchMedia("(prefers-reduced-motion: reduce)");
7130
+ const mediaQuery = safeMatchMedia("(prefers-reduced-motion: reduce)");
7234
7131
 
7235
- if (mediaQuery) {
7236
- this._handleMotionChange(mediaQuery);
7132
+ if (mediaQuery) {
7133
+ this._handleMotionChange(mediaQuery);
7237
7134
 
7238
- const handleChange = () => {
7239
- this._handleMotionChange(mediaQuery);
7135
+ const handleChange = () => {
7136
+ this._handleMotionChange(mediaQuery);
7240
7137
 
7241
- container.refresh().catch(() => {});
7242
- };
7138
+ container.refresh().catch(() => {});
7139
+ };
7243
7140
 
7244
- if (mediaQuery.addEventListener !== undefined) {
7245
- mediaQuery.addEventListener("change", handleChange);
7246
- } else if (mediaQuery.addListener !== undefined) {
7247
- mediaQuery.addListener(handleChange);
7248
- }
7141
+ if (mediaQuery.addEventListener !== undefined) {
7142
+ mediaQuery.addEventListener("change", handleChange);
7143
+ } else if (mediaQuery.addListener !== undefined) {
7144
+ mediaQuery.addListener(handleChange);
7249
7145
  }
7146
+ } else {
7147
+ this.reduceFactor = 1;
7250
7148
  }
7251
7149
  } else {
7252
7150
  this.reduceFactor = 1;
@@ -8053,6 +7951,17 @@ class Loader {
8053
7951
 
8054
7952
  }
8055
7953
  ;// CONCATENATED MODULE: ../../engine/dist/esm/Core/Utils/Plugins.js
7954
+ function getItemsFromInitializer(container, map, initializers, force = false) {
7955
+ let res = map.get(container);
7956
+
7957
+ if (!res || force) {
7958
+ res = [...initializers.values()].map(t => t(container));
7959
+ map.set(container, res);
7960
+ }
7961
+
7962
+ return res;
7963
+ }
7964
+
8056
7965
  class Plugins {
8057
7966
  constructor(engine) {
8058
7967
  this._engine = engine;
@@ -8125,25 +8034,11 @@ class Plugins {
8125
8034
  }
8126
8035
 
8127
8036
  getInteractors(container, force = false) {
8128
- let res = this.interactors.get(container);
8129
-
8130
- if (!res || force) {
8131
- res = [...this.interactorsInitializers.values()].map(t => t(container));
8132
- this.interactors.set(container, res);
8133
- }
8134
-
8135
- return res;
8037
+ return getItemsFromInitializer(container, this.interactors, this.interactorsInitializers, force);
8136
8038
  }
8137
8039
 
8138
8040
  getMovers(container, force = false) {
8139
- let res = this.movers.get(container);
8140
-
8141
- if (!res || force) {
8142
- res = [...this.moversInitializers.values()].map(t => t(container));
8143
- this.movers.set(container, res);
8144
- }
8145
-
8146
- return res;
8041
+ return getItemsFromInitializer(container, this.movers, this.moversInitializers, force);
8147
8042
  }
8148
8043
 
8149
8044
  getPathGenerator(type) {
@@ -8167,14 +8062,7 @@ class Plugins {
8167
8062
  }
8168
8063
 
8169
8064
  getUpdaters(container, force = false) {
8170
- let res = this.updaters.get(container);
8171
-
8172
- if (!res || force) {
8173
- res = [...this.updatersInitializers.values()].map(t => t(container));
8174
- this.updaters.set(container, res);
8175
- }
8176
-
8177
- return res;
8065
+ return getItemsFromInitializer(container, this.updaters, this.updatersInitializers, force);
8178
8066
  }
8179
8067
 
8180
8068
  loadOptions(options, sourceOptions) {
@@ -8336,6 +8224,7 @@ class Engine {
8336
8224
 
8337
8225
  class HslColorManager {
8338
8226
  constructor() {
8227
+ this.key = "hsl";
8339
8228
  this.stringPrefix = "hsl";
8340
8229
  }
8341
8230
 
@@ -8385,6 +8274,7 @@ class HslColorManager {
8385
8274
 
8386
8275
  class RgbColorManager {
8387
8276
  constructor() {
8277
+ this.key = "rgb";
8388
8278
  this.stringPrefix = "rgb";
8389
8279
  }
8390
8280
 
@@ -8453,8 +8343,8 @@ class ParticlesInteractorBase {
8453
8343
 
8454
8344
  const rgbColorManager = new RgbColorManager(),
8455
8345
  hslColorManager = new HslColorManager();
8456
- addColorManager("rgb", rgbColorManager);
8457
- addColorManager("hsl", hslColorManager);
8346
+ addColorManager(rgbColorManager);
8347
+ addColorManager(hslColorManager);
8458
8348
  const tsParticles = new Engine();
8459
8349
  tsParticles.init();
8460
8350
 
@@ -8633,10 +8523,6 @@ tsParticles.init();
8633
8523
 
8634
8524
 
8635
8525
 
8636
-
8637
-
8638
-
8639
-
8640
8526
 
8641
8527
 
8642
8528
 
@@ -9045,11 +8931,15 @@ class AbsorbersPlugin {
9045
8931
  }
9046
8932
 
9047
8933
  const optionsCast = options;
9048
- optionsCast.absorbers = executeOnSingleOrMultiple(source === null || source === void 0 ? void 0 : source.absorbers, absorber => {
9049
- const tmp = new Absorber();
9050
- tmp.load(absorber);
9051
- return tmp;
9052
- });
8934
+
8935
+ if (source === null || source === void 0 ? void 0 : source.absorbers) {
8936
+ optionsCast.absorbers = executeOnSingleOrMultiple(source.absorbers, absorber => {
8937
+ const tmp = new Absorber();
8938
+ tmp.load(absorber);
8939
+ return tmp;
8940
+ });
8941
+ }
8942
+
9053
8943
  optionsCast.interactivity.modes.absorbers = executeOnSingleOrMultiple((_b = (_a = source === null || source === void 0 ? void 0 : source.interactivity) === null || _a === void 0 ? void 0 : _a.modes) === null || _b === void 0 ? void 0 : _b.absorbers, absorber => {
9054
8944
  const tmp = new Absorber();
9055
8945
  tmp.load(absorber);
@@ -10163,11 +10053,15 @@ class EmittersPlugin {
10163
10053
  }
10164
10054
 
10165
10055
  const optionsCast = options;
10166
- optionsCast.emitters = executeOnSingleOrMultiple(source === null || source === void 0 ? void 0 : source.emitters, emitter => {
10167
- const tmp = new Emitter();
10168
- tmp.load(emitter);
10169
- return tmp;
10170
- });
10056
+
10057
+ if (source === null || source === void 0 ? void 0 : source.emitters) {
10058
+ optionsCast.emitters = executeOnSingleOrMultiple(source.emitters, emitter => {
10059
+ const tmp = new Emitter();
10060
+ tmp.load(emitter);
10061
+ return tmp;
10062
+ });
10063
+ }
10064
+
10171
10065
  const interactivityEmitters = (_b = (_a = source === null || source === void 0 ? void 0 : source.interactivity) === null || _a === void 0 ? void 0 : _a.modes) === null || _b === void 0 ? void 0 : _b.emitters;
10172
10066
 
10173
10067
  if (interactivityEmitters) {
@@ -10385,7 +10279,7 @@ async function loadExternalTrailInteraction(engine) {
10385
10279
 
10386
10280
 
10387
10281
  // EXTERNAL MODULE: ../../plugins/polygonMask/dist/esm/pathseg.js
10388
- var pathseg = __webpack_require__(417);
10282
+ var pathseg = __webpack_require__(74);
10389
10283
  ;// CONCATENATED MODULE: ../../plugins/polygonMask/dist/esm/Options/Classes/PolygonMaskDrawStroke.js
10390
10284
 
10391
10285
  class PolygonMaskDrawStroke {
@@ -11449,20 +11343,85 @@ const initPjs = engine => {
11449
11343
  };
11450
11344
 
11451
11345
 
11452
- ;// CONCATENATED MODULE: ../../updaters/angle/dist/esm/AngleUpdater.js
11346
+ ;// CONCATENATED MODULE: ../../updaters/angle/dist/esm/Options/Classes/RotateAnimation.js
11347
+
11348
+ class RotateAnimation {
11349
+ constructor() {
11350
+ this.enable = false;
11351
+ this.speed = 0;
11352
+ this.decay = 0;
11353
+ this.sync = false;
11354
+ }
11355
+
11356
+ load(data) {
11357
+ if (!data) {
11358
+ return;
11359
+ }
11360
+
11361
+ if (data.enable !== undefined) {
11362
+ this.enable = data.enable;
11363
+ }
11364
+
11365
+ if (data.speed !== undefined) {
11366
+ this.speed = setRangeValue(data.speed);
11367
+ }
11368
+
11369
+ if (data.decay !== undefined) {
11370
+ this.decay = setRangeValue(data.decay);
11371
+ }
11372
+
11373
+ if (data.sync !== undefined) {
11374
+ this.sync = data.sync;
11375
+ }
11376
+ }
11377
+
11378
+ }
11379
+ ;// CONCATENATED MODULE: ../../updaters/angle/dist/esm/Options/Classes/Rotate.js
11380
+
11381
+
11382
+ class Rotate extends ValueWithRandom {
11383
+ constructor() {
11384
+ super();
11385
+ this.animation = new RotateAnimation();
11386
+ this.direction = "clockwise";
11387
+ this.path = false;
11388
+ this.value = 0;
11389
+ }
11390
+
11391
+ load(data) {
11392
+ if (!data) {
11393
+ return;
11394
+ }
11395
+
11396
+ super.load(data);
11397
+
11398
+ if (data.direction !== undefined) {
11399
+ this.direction = data.direction;
11400
+ }
11401
+
11402
+ this.animation.load(data.animation);
11403
+
11404
+ if (data.path !== undefined) {
11405
+ this.path = data.path;
11406
+ }
11407
+ }
11408
+
11409
+ }
11410
+ ;// CONCATENATED MODULE: ../../updaters/angle/dist/esm/RotateUpdater.js
11411
+
11453
11412
 
11454
11413
 
11455
11414
  function updateAngle(particle, delta) {
11456
11415
  var _a, _b;
11457
11416
 
11458
- const rotate = particle.rotate;
11417
+ const rotate = particle.rotate,
11418
+ rotateOptions = particle.options.rotate;
11459
11419
 
11460
- if (!rotate) {
11420
+ if (!rotate || !rotateOptions) {
11461
11421
  return;
11462
11422
  }
11463
11423
 
11464
- const rotateOptions = particle.options.rotate,
11465
- rotateAnimation = rotateOptions.animation,
11424
+ const rotateAnimation = rotateOptions.animation,
11466
11425
  speed = ((_a = rotate.velocity) !== null && _a !== void 0 ? _a : 0) * delta.factor,
11467
11426
  max = 2 * Math.PI,
11468
11427
  decay = (_b = rotate.decay) !== null && _b !== void 0 ? _b : 1;
@@ -11497,17 +11456,23 @@ function updateAngle(particle, delta) {
11497
11456
  }
11498
11457
  }
11499
11458
 
11500
- class AngleUpdater {
11459
+ class RotateUpdater {
11501
11460
  constructor(container) {
11502
11461
  this.container = container;
11503
11462
  }
11504
11463
 
11505
11464
  init(particle) {
11506
11465
  const rotateOptions = particle.options.rotate;
11466
+
11467
+ if (!rotateOptions) {
11468
+ return;
11469
+ }
11470
+
11507
11471
  particle.rotate = {
11508
11472
  enable: rotateOptions.animation.enable,
11509
11473
  value: getRangeValue(rotateOptions.value) * Math.PI / 180
11510
11474
  };
11475
+ particle.pathRotation = rotateOptions.path;
11511
11476
  let rotateDirection = rotateOptions.direction;
11512
11477
 
11513
11478
  if (rotateDirection === "random") {
@@ -11526,7 +11491,7 @@ class AngleUpdater {
11526
11491
  break;
11527
11492
  }
11528
11493
 
11529
- const rotateAnimation = particle.options.rotate.animation;
11494
+ const rotateAnimation = rotateOptions.animation;
11530
11495
 
11531
11496
  if (rotateAnimation.enable) {
11532
11497
  particle.rotate.decay = 1 - getRangeValue(rotateAnimation.decay);
@@ -11541,9 +11506,23 @@ class AngleUpdater {
11541
11506
  }
11542
11507
 
11543
11508
  isEnabled(particle) {
11544
- const rotate = particle.options.rotate,
11545
- rotateAnimation = rotate.animation;
11546
- return !particle.destroyed && !particle.spawning && rotateAnimation.enable && !rotate.path;
11509
+ const rotate = particle.options.rotate;
11510
+
11511
+ if (!rotate) {
11512
+ return false;
11513
+ }
11514
+
11515
+ return !particle.destroyed && !particle.spawning && rotate.animation.enable && !rotate.path;
11516
+ }
11517
+
11518
+ loadOptions(options, ...sources) {
11519
+ if (!options.rotate) {
11520
+ options.rotate = new Rotate();
11521
+ }
11522
+
11523
+ for (const source of sources) {
11524
+ options.rotate.load(source === null || source === void 0 ? void 0 : source.rotate);
11525
+ }
11547
11526
  }
11548
11527
 
11549
11528
  update(particle, delta) {
@@ -11561,7 +11540,7 @@ class AngleUpdater {
11561
11540
  ;// CONCATENATED MODULE: ../../updaters/angle/dist/esm/index.js
11562
11541
 
11563
11542
  async function loadAngleUpdater(engine) {
11564
- await engine.addParticleUpdater("angle", container => new AngleUpdater(container));
11543
+ await engine.addParticleUpdater("rotate", container => new RotateUpdater(container));
11565
11544
  }
11566
11545
  ;// CONCATENATED MODULE: ../../move/base/dist/esm/Utils.js
11567
11546
 
@@ -15570,9 +15549,31 @@ function drawLinkTriangle(context, pos1, pos2, pos3, backgroundMask, composite,
15570
15549
  ;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/LinkInstance.js
15571
15550
 
15572
15551
 
15552
+
15553
+ function getLinkKey(ids) {
15554
+ ids.sort((a, b) => a - b);
15555
+ return ids.join("_");
15556
+ }
15557
+
15558
+ function setLinkFrequency(particles, dictionary) {
15559
+ const key = getLinkKey(particles.map(t => t.id));
15560
+ let res = dictionary.get(key);
15561
+
15562
+ if (res === undefined) {
15563
+ res = getRandom();
15564
+ dictionary.set(key, res);
15565
+ }
15566
+
15567
+ return res;
15568
+ }
15569
+
15573
15570
  class LinkInstance {
15574
15571
  constructor(container) {
15575
15572
  this.container = container;
15573
+ this._freqs = {
15574
+ links: new Map(),
15575
+ triangles: new Map()
15576
+ };
15576
15577
  }
15577
15578
 
15578
15579
  drawParticle(context, particle) {
@@ -15586,7 +15587,7 @@ class LinkInstance {
15586
15587
  }
15587
15588
 
15588
15589
  context.save();
15589
- const p1Links = particle.links.filter(l => pOptions.links && container.particles.getLinkFrequency(particle, l.destination) <= pOptions.links.frequency);
15590
+ const p1Links = particle.links.filter(l => pOptions.links && this.getLinkFrequency(particle, l.destination) <= pOptions.links.frequency);
15590
15591
 
15591
15592
  for (const link of p1Links) {
15592
15593
  this.drawTriangles(container, pOptions, particle, link, p1Links);
@@ -15599,6 +15600,11 @@ class LinkInstance {
15599
15600
  context.restore();
15600
15601
  }
15601
15602
 
15603
+ init() {
15604
+ this._freqs.links = new Map();
15605
+ this._freqs.triangles = new Map();
15606
+ }
15607
+
15602
15608
  particleCreated(particle) {
15603
15609
  particle.links = [];
15604
15610
 
@@ -15708,15 +15714,14 @@ class LinkInstance {
15708
15714
  drawTriangles(container, options, p1, link, p1Links) {
15709
15715
  var _a, _b, _c;
15710
15716
 
15711
- const p2 = link.destination,
15712
- particles = container.particles;
15717
+ const p2 = link.destination;
15713
15718
 
15714
15719
  if (!(((_a = options.links) === null || _a === void 0 ? void 0 : _a.triangles.enable) && ((_b = p2.options.links) === null || _b === void 0 ? void 0 : _b.triangles.enable))) {
15715
15720
  return;
15716
15721
  }
15717
15722
 
15718
15723
  const vertices = (_c = p2.links) === null || _c === void 0 ? void 0 : _c.filter(t => {
15719
- const linkFreq = container.particles.getLinkFrequency(p2, t.destination);
15724
+ const linkFreq = this.getLinkFrequency(p2, t.destination);
15720
15725
  return p2.options.links && linkFreq <= p2.options.links.frequency && p1Links.findIndex(l => l.destination === t.destination) >= 0;
15721
15726
  });
15722
15727
 
@@ -15726,7 +15731,7 @@ class LinkInstance {
15726
15731
 
15727
15732
  for (const vertex of vertices) {
15728
15733
  const p3 = vertex.destination,
15729
- triangleFreq = particles.getTriangleFrequency(p1, p2, p3);
15734
+ triangleFreq = this.getTriangleFrequency(p1, p2, p3);
15730
15735
 
15731
15736
  if (triangleFreq > options.links.triangles.frequency) {
15732
15737
  continue;
@@ -15736,6 +15741,14 @@ class LinkInstance {
15736
15741
  }
15737
15742
  }
15738
15743
 
15744
+ getLinkFrequency(p1, p2) {
15745
+ return setLinkFrequency([p1, p2], this._freqs.links);
15746
+ }
15747
+
15748
+ getTriangleFrequency(p1, p2, p3) {
15749
+ return setLinkFrequency([p1, p2, p3], this._freqs.triangles);
15750
+ }
15751
+
15739
15752
  }
15740
15753
  ;// CONCATENATED MODULE: ../../interactions/particles/links/dist/esm/plugin.js
15741
15754