@tsparticles/engine 4.0.0-beta.9 → 4.0.0

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.
Files changed (84) hide show
  1. package/browser/Core/CanvasManager.js +74 -37
  2. package/browser/Core/Engine.js +23 -8
  3. package/browser/Core/Particle.js +3 -3
  4. package/browser/Core/ParticlesManager.js +157 -78
  5. package/browser/Core/Retina.js +2 -3
  6. package/browser/Core/Utils/EventListeners.js +1 -1
  7. package/browser/Options/Classes/Particles/Fill.js +0 -2
  8. package/browser/Options/Classes/Particles/Paint.js +25 -0
  9. package/browser/Options/Classes/Particles/ParticlesOptions.js +54 -48
  10. package/browser/Utils/CanvasUtils.js +3 -3
  11. package/browser/Utils/LogUtils.js +32 -15
  12. package/browser/Utils/Utils.js +1 -0
  13. package/browser/browser.js +5 -0
  14. package/browser/exports.js +1 -0
  15. package/browser/index.js +0 -1
  16. package/cjs/Core/CanvasManager.js +74 -37
  17. package/cjs/Core/Engine.js +23 -8
  18. package/cjs/Core/Particle.js +3 -3
  19. package/cjs/Core/ParticlesManager.js +157 -78
  20. package/cjs/Core/Retina.js +2 -3
  21. package/cjs/Core/Utils/EventListeners.js +1 -1
  22. package/cjs/Options/Classes/Particles/Fill.js +0 -2
  23. package/cjs/Options/Classes/Particles/Paint.js +25 -0
  24. package/cjs/Options/Classes/Particles/ParticlesOptions.js +54 -48
  25. package/cjs/Utils/CanvasUtils.js +3 -3
  26. package/cjs/Utils/LogUtils.js +32 -15
  27. package/cjs/Utils/Utils.js +1 -0
  28. package/cjs/browser.js +5 -0
  29. package/cjs/exports.js +1 -0
  30. package/cjs/index.js +0 -1
  31. package/esm/Core/CanvasManager.js +74 -37
  32. package/esm/Core/Engine.js +23 -8
  33. package/esm/Core/Particle.js +3 -3
  34. package/esm/Core/ParticlesManager.js +157 -78
  35. package/esm/Core/Retina.js +2 -3
  36. package/esm/Core/Utils/EventListeners.js +1 -1
  37. package/esm/Options/Classes/Particles/Fill.js +0 -2
  38. package/esm/Options/Classes/Particles/Paint.js +25 -0
  39. package/esm/Options/Classes/Particles/ParticlesOptions.js +54 -48
  40. package/esm/Utils/CanvasUtils.js +3 -3
  41. package/esm/Utils/LogUtils.js +32 -15
  42. package/esm/Utils/Utils.js +1 -0
  43. package/esm/browser.js +5 -0
  44. package/esm/exports.js +1 -0
  45. package/esm/index.js +0 -1
  46. package/package.json +8 -1
  47. package/report.html +4949 -94
  48. package/scripts/install.js +321 -220
  49. package/tsparticles.engine.js +5293 -939
  50. package/tsparticles.engine.min.js +1 -2
  51. package/types/Core/CanvasManager.d.ts +3 -2
  52. package/types/Core/Container.d.ts +1 -2
  53. package/types/Core/Interfaces/IContainerPlugin.d.ts +7 -8
  54. package/types/Core/Interfaces/IDrawParticleParams.d.ts +1 -2
  55. package/types/Core/Interfaces/ILoadParams.d.ts +1 -1
  56. package/types/Core/Interfaces/IPalette.d.ts +4 -2
  57. package/types/Core/Interfaces/IParticleUpdater.d.ts +1 -2
  58. package/types/Core/Interfaces/IShapeDrawData.d.ts +1 -2
  59. package/types/Core/Particle.d.ts +1 -0
  60. package/types/Core/ParticlesManager.d.ts +11 -5
  61. package/types/Core/RenderManager.d.ts +2 -3
  62. package/types/Core/Utils/PluginManager.d.ts +5 -6
  63. package/types/Options/Classes/Options.d.ts +1 -2
  64. package/types/Options/Classes/Particles/Fill.d.ts +1 -1
  65. package/types/Options/Classes/Particles/Paint.d.ts +12 -0
  66. package/types/Options/Classes/Particles/ParticlesOptions.d.ts +2 -4
  67. package/types/Options/Interfaces/Particles/IPaint.d.ts +10 -0
  68. package/types/Options/Interfaces/Particles/IParticlesOptions.d.ts +2 -4
  69. package/types/Utils/CanvasUtils.d.ts +4 -5
  70. package/types/Utils/LogUtils.d.ts +2 -3
  71. package/types/Utils/Utils.d.ts +1 -2
  72. package/types/browser.d.ts +1 -0
  73. package/types/export-types.d.ts +1 -1
  74. package/types/exports.d.ts +1 -0
  75. package/types/{bundle.d.ts → index.lazy.d.ts} +1 -0
  76. package/67.min.js +0 -1
  77. package/dist_browser_Core_Container_js.js +0 -102
  78. package/types/Types/CanvasContextType.d.ts +0 -1
  79. /package/browser/{Types/CanvasContextType.js → Options/Interfaces/Particles/IPaint.js} +0 -0
  80. /package/browser/{bundle.js → index.lazy.js} +0 -0
  81. /package/cjs/{Types/CanvasContextType.js → Options/Interfaces/Particles/IPaint.js} +0 -0
  82. /package/cjs/{bundle.js → index.lazy.js} +0 -0
  83. /package/esm/{Types/CanvasContextType.js → Options/Interfaces/Particles/IPaint.js} +0 -0
  84. /package/esm/{bundle.js → index.lazy.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { countOffset, defaultDensityFactor, defaultRemoveQuantity, deleteCount, lengthOffset, minCount, minIndex, minLimit, spatialHashGridCellSize, squareExp, } from "./Utils/Constants.js";
1
+ import { countOffset, defaultDensityFactor, defaultRemoveQuantity, deleteCount, double, empty, minCount, minIndex, minLimit, one, spatialHashGridCellSize, squareExp, } from "./Utils/Constants.js";
2
2
  import { EventType } from "../Enums/Types/EventType.js";
3
3
  import { LimitMode } from "../Enums/Modes/LimitMode.js";
4
4
  import { Particle } from "./Particle.js";
@@ -12,10 +12,8 @@ export class ParticlesManager {
12
12
  _container;
13
13
  _groupLimits;
14
14
  _limit;
15
- _maxZIndex;
16
- _minZIndex;
17
- _needsSort;
18
15
  _nextId;
16
+ _particleBuckets;
19
17
  _particleResetPlugins;
20
18
  _particleUpdatePlugins;
21
19
  _pluginManager;
@@ -24,19 +22,17 @@ export class ParticlesManager {
24
22
  _postUpdatePlugins;
25
23
  _resizeFactor;
26
24
  _updatePlugins;
27
- _zArray;
25
+ _zBuckets;
28
26
  constructor(pluginManager, container) {
29
27
  this._pluginManager = pluginManager;
30
28
  this._container = container;
31
29
  this._nextId = 0;
32
30
  this._array = [];
33
- this._zArray = [];
34
31
  this._pool = [];
35
32
  this._limit = 0;
36
33
  this._groupLimits = new Map();
37
- this._needsSort = false;
38
- this._minZIndex = 0;
39
- this._maxZIndex = 0;
34
+ this._particleBuckets = new Map();
35
+ this._zBuckets = this._createBuckets(this._container.zLayers);
40
36
  this.grid = new SpatialHashGrid(spatialHashGridCellSize);
41
37
  this.checkParticlePositionPlugins = [];
42
38
  this._particleResetPlugins = [];
@@ -80,7 +76,7 @@ export class ParticlesManager {
80
76
  return;
81
77
  }
82
78
  this._array.push(particle);
83
- this._zArray.push(particle);
79
+ this._insertParticleIntoBucket(particle);
84
80
  this._nextId++;
85
81
  this._container.dispatchEvent(EventType.particleAdded, {
86
82
  particle,
@@ -94,12 +90,14 @@ export class ParticlesManager {
94
90
  }
95
91
  clear() {
96
92
  this._array = [];
97
- this._zArray = [];
93
+ this._particleBuckets.clear();
94
+ this._resetBuckets(this._container.zLayers);
98
95
  }
99
96
  destroy() {
100
97
  this._array = [];
101
98
  this._pool.length = 0;
102
- this._zArray = [];
99
+ this._particleBuckets.clear();
100
+ this._zBuckets = [];
103
101
  this.checkParticlePositionPlugins = [];
104
102
  this._particleResetPlugins = [];
105
103
  this._particleUpdatePlugins = [];
@@ -108,8 +106,14 @@ export class ParticlesManager {
108
106
  this._updatePlugins = [];
109
107
  }
110
108
  drawParticles(delta) {
111
- for (const particle of this._zArray) {
112
- particle.draw(delta);
109
+ for (let i = this._zBuckets.length - one; i >= minIndex; i--) {
110
+ const bucket = this._zBuckets[i];
111
+ if (!bucket) {
112
+ continue;
113
+ }
114
+ for (const particle of bucket) {
115
+ particle.draw(delta);
116
+ }
113
117
  }
114
118
  }
115
119
  filter(condition) {
@@ -123,15 +127,14 @@ export class ParticlesManager {
123
127
  }
124
128
  async init() {
125
129
  const container = this._container, options = container.actualOptions;
126
- this._minZIndex = 0;
127
- this._maxZIndex = 0;
128
- this._needsSort = false;
129
130
  this.checkParticlePositionPlugins = [];
130
131
  this._updatePlugins = [];
131
132
  this._particleUpdatePlugins = [];
132
133
  this._postUpdatePlugins = [];
133
134
  this._particleResetPlugins = [];
134
135
  this._postParticleUpdatePlugins = [];
136
+ this._particleBuckets.clear();
137
+ this._resetBuckets(container.zLayers);
135
138
  this.grid = new SpatialHashGrid(spatialHashGridCellSize * container.retina.pixelRatio);
136
139
  for (const plugin of container.plugins) {
137
140
  if (plugin.redrawInit) {
@@ -232,79 +235,25 @@ export class ParticlesManager {
232
235
  }
233
236
  this._applyDensity(options.particles, pluginsCount);
234
237
  }
235
- setLastZIndex(zIndex) {
236
- this._needsSort ||= zIndex >= this._maxZIndex || (zIndex > this._minZIndex && zIndex < this._maxZIndex);
237
- }
238
238
  setResizeFactor(factor) {
239
239
  this._resizeFactor = factor;
240
240
  }
241
241
  update(delta) {
242
- const particlesToDelete = new Set();
243
242
  this.grid.clear();
244
243
  for (const plugin of this._updatePlugins) {
245
244
  plugin.update?.(delta);
246
245
  }
247
- const resizeFactor = this._resizeFactor;
248
- for (const particle of this._array) {
249
- if (resizeFactor && !particle.ignoresResizeRatio) {
250
- particle.position.x *= resizeFactor.width;
251
- particle.position.y *= resizeFactor.height;
252
- particle.initialPosition.x *= resizeFactor.width;
253
- particle.initialPosition.y *= resizeFactor.height;
254
- }
255
- particle.ignoresResizeRatio = false;
256
- for (const plugin of this._particleResetPlugins) {
257
- plugin.particleReset?.(particle);
258
- }
259
- for (const plugin of this._particleUpdatePlugins) {
260
- if (particle.destroyed) {
261
- break;
262
- }
263
- plugin.particleUpdate?.(particle, delta);
264
- }
265
- if (particle.destroyed) {
266
- particlesToDelete.add(particle);
267
- continue;
268
- }
269
- this.grid.insert(particle);
270
- }
246
+ const particlesToDelete = this._updateParticlesPhase1(delta);
271
247
  for (const plugin of this._postUpdatePlugins) {
272
248
  plugin.postUpdate?.(delta);
273
249
  }
274
- for (const particle of this._array) {
275
- if (particle.destroyed) {
276
- particlesToDelete.add(particle);
277
- continue;
278
- }
279
- for (const updater of this._container.particleUpdaters) {
280
- updater.update(particle, delta);
281
- }
282
- if (!particle.destroyed && !particle.spawning) {
283
- for (const plugin of this._postParticleUpdatePlugins) {
284
- plugin.postParticleUpdate?.(particle, delta);
285
- }
286
- }
287
- else if (particle.destroyed) {
288
- particlesToDelete.add(particle);
289
- }
290
- }
250
+ this._updateParticlesPhase2(delta, particlesToDelete);
291
251
  if (particlesToDelete.size) {
292
252
  for (const particle of particlesToDelete) {
293
253
  this.remove(particle);
294
254
  }
295
255
  }
296
256
  delete this._resizeFactor;
297
- if (this._needsSort) {
298
- const zArray = this._zArray;
299
- zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
300
- const firstItem = zArray[minIndex], lastItem = zArray[zArray.length - lengthOffset];
301
- if (!firstItem || !lastItem) {
302
- return;
303
- }
304
- this._maxZIndex = firstItem.position.z;
305
- this._minZIndex = lastItem.position.z;
306
- this._needsSort = false;
307
- }
308
257
  }
309
258
  _addToPool = (...particles) => {
310
259
  this._pool.push(...particles);
@@ -334,13 +283,52 @@ export class ParticlesManager {
334
283
  this.removeQuantity(particlesCount - particlesNumber, group);
335
284
  }
336
285
  };
286
+ _createBuckets = (zLayers) => {
287
+ const bucketCount = Math.max(Math.floor(zLayers), one);
288
+ return Array.from({ length: bucketCount }, () => []);
289
+ };
290
+ _getBucketIndex = (zIndex) => {
291
+ const maxBucketIndex = this._zBuckets.length - one;
292
+ if (maxBucketIndex <= minIndex) {
293
+ return minIndex;
294
+ }
295
+ return Math.min(Math.max(Math.floor(zIndex), minIndex), maxBucketIndex);
296
+ };
297
+ _getParticleInsertIndex = (bucket, particleId) => {
298
+ let start = minIndex, end = bucket.length;
299
+ while (start < end) {
300
+ const middle = Math.floor((start + end) / double), middleParticle = bucket[middle];
301
+ if (!middleParticle) {
302
+ end = middle;
303
+ continue;
304
+ }
305
+ if (middleParticle.id < particleId) {
306
+ start = middle + one;
307
+ }
308
+ else {
309
+ end = middle;
310
+ }
311
+ }
312
+ return start;
313
+ };
337
314
  _initDensityFactor = densityOptions => {
338
315
  const container = this._container;
339
- if (!container.canvas.element || !densityOptions.enable) {
316
+ if (!densityOptions.enable) {
340
317
  return defaultDensityFactor;
341
318
  }
342
- const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
343
- return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
319
+ const canvasSize = container.canvas.size, pxRatio = container.retina.pixelRatio;
320
+ if (!canvasSize.width || !canvasSize.height) {
321
+ return defaultDensityFactor;
322
+ }
323
+ return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp));
324
+ };
325
+ _insertParticleIntoBucket = (particle) => {
326
+ const bucketIndex = this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
327
+ if (!bucket) {
328
+ return;
329
+ }
330
+ bucket.splice(this._getParticleInsertIndex(bucket, particle.id), empty, particle);
331
+ this._particleBuckets.set(particle.id, bucketIndex);
344
332
  };
345
333
  _removeParticle = (index, group, override) => {
346
334
  const particle = this._array[index];
@@ -350,9 +338,8 @@ export class ParticlesManager {
350
338
  if (particle.group !== group) {
351
339
  return false;
352
340
  }
353
- const zIdx = this._zArray.indexOf(particle);
354
341
  this._array.splice(index, deleteCount);
355
- this._zArray.splice(zIdx, deleteCount);
342
+ this._removeParticleFromBucket(particle);
356
343
  particle.destroy(override);
357
344
  this._container.dispatchEvent(EventType.particleRemoved, {
358
345
  particle,
@@ -360,4 +347,96 @@ export class ParticlesManager {
360
347
  this._addToPool(particle);
361
348
  return true;
362
349
  };
350
+ _removeParticleFromBucket = (particle) => {
351
+ const bucketIndex = this._particleBuckets.get(particle.id) ?? this._getBucketIndex(particle.position.z), bucket = this._zBuckets[bucketIndex];
352
+ if (!bucket) {
353
+ this._particleBuckets.delete(particle.id);
354
+ return;
355
+ }
356
+ const particleIndex = this._getParticleInsertIndex(bucket, particle.id);
357
+ if (bucket[particleIndex]?.id !== particle.id) {
358
+ this._particleBuckets.delete(particle.id);
359
+ return;
360
+ }
361
+ bucket.splice(particleIndex, deleteCount);
362
+ this._particleBuckets.delete(particle.id);
363
+ };
364
+ _resetBuckets = (zLayers) => {
365
+ const bucketCount = Math.max(Math.floor(zLayers), one);
366
+ if (this._zBuckets.length !== bucketCount) {
367
+ this._zBuckets = this._createBuckets(bucketCount);
368
+ return;
369
+ }
370
+ for (const bucket of this._zBuckets) {
371
+ bucket.length = minIndex;
372
+ }
373
+ };
374
+ _updateParticleBucket = (particle) => {
375
+ const newBucketIndex = this._getBucketIndex(particle.position.z), currentBucketIndex = this._particleBuckets.get(particle.id);
376
+ if (currentBucketIndex === undefined) {
377
+ this._insertParticleIntoBucket(particle);
378
+ return;
379
+ }
380
+ if (currentBucketIndex === newBucketIndex) {
381
+ return;
382
+ }
383
+ const currentBucket = this._zBuckets[currentBucketIndex];
384
+ if (currentBucket) {
385
+ const particleIndex = this._getParticleInsertIndex(currentBucket, particle.id);
386
+ if (currentBucket[particleIndex]?.id === particle.id) {
387
+ currentBucket.splice(particleIndex, deleteCount);
388
+ }
389
+ }
390
+ const newBucket = this._zBuckets[newBucketIndex];
391
+ if (!newBucket) {
392
+ this._particleBuckets.set(particle.id, newBucketIndex);
393
+ return;
394
+ }
395
+ newBucket.splice(this._getParticleInsertIndex(newBucket, particle.id), empty, particle);
396
+ this._particleBuckets.set(particle.id, newBucketIndex);
397
+ };
398
+ _updateParticlesPhase1 = (delta) => {
399
+ const particlesToDelete = new Set(), resizeFactor = this._resizeFactor;
400
+ for (const particle of this._array) {
401
+ if (resizeFactor && !particle.ignoresResizeRatio) {
402
+ particle.position.x *= resizeFactor.width;
403
+ particle.position.y *= resizeFactor.height;
404
+ particle.initialPosition.x *= resizeFactor.width;
405
+ particle.initialPosition.y *= resizeFactor.height;
406
+ }
407
+ particle.ignoresResizeRatio = false;
408
+ for (const plugin of this._particleResetPlugins) {
409
+ plugin.particleReset?.(particle);
410
+ }
411
+ for (const plugin of this._particleUpdatePlugins) {
412
+ if (particle.destroyed) {
413
+ break;
414
+ }
415
+ plugin.particleUpdate?.(particle, delta);
416
+ }
417
+ if (particle.destroyed) {
418
+ particlesToDelete.add(particle);
419
+ continue;
420
+ }
421
+ this.grid.insert(particle);
422
+ }
423
+ return particlesToDelete;
424
+ };
425
+ _updateParticlesPhase2 = (delta, particlesToDelete) => {
426
+ for (const particle of this._array) {
427
+ if (particle.destroyed) {
428
+ particlesToDelete.add(particle);
429
+ continue;
430
+ }
431
+ for (const updater of this._container.particleUpdaters) {
432
+ updater.update(particle, delta);
433
+ }
434
+ if (!particle.spawning) {
435
+ for (const plugin of this._postParticleUpdatePlugins) {
436
+ plugin.postParticleUpdate?.(particle, delta);
437
+ }
438
+ }
439
+ this._updateParticleBucket(particle);
440
+ }
441
+ };
363
442
  }
@@ -13,9 +13,8 @@ export class Retina {
13
13
  const container = this.container, options = container.actualOptions;
14
14
  this.pixelRatio = options.detectRetina ? devicePixelRatio : defaultRatio;
15
15
  this.reduceFactor = defaultReduceFactor;
16
- const ratio = this.pixelRatio, canvas = container.canvas;
17
- if (canvas.element) {
18
- const element = canvas.element;
16
+ const ratio = this.pixelRatio, canvas = container.canvas, element = canvas.domElement;
17
+ if (element) {
19
18
  canvas.size.width = element.offsetWidth * ratio;
20
19
  canvas.size.height = element.offsetHeight * ratio;
21
20
  }
@@ -66,7 +66,7 @@ export class EventListeners {
66
66
  manageListener(globalThis, resizeEvent, handlers.resize, add);
67
67
  return;
68
68
  }
69
- const canvasEl = container.canvas.element;
69
+ const canvasEl = container.canvas.domElement;
70
70
  if (this._resizeObserver && !add) {
71
71
  if (canvasEl) {
72
72
  this._resizeObserver.unobserve(canvasEl);
@@ -7,8 +7,6 @@ export class Fill {
7
7
  opacity;
8
8
  constructor() {
9
9
  this.enable = true;
10
- this.color = new AnimatableColor();
11
- this.color.value = "#fff";
12
10
  this.opacity = 1;
13
11
  }
14
12
  load(data) {
@@ -0,0 +1,25 @@
1
+ import { AnimatableColor } from "../AnimatableColor.js";
2
+ import { Fill } from "./Fill.js";
3
+ import { Stroke } from "./Stroke.js";
4
+ import { isNull } from "../../../Utils/TypeUtils.js";
5
+ export class Paint {
6
+ color;
7
+ fill;
8
+ stroke;
9
+ load(data) {
10
+ if (isNull(data)) {
11
+ return;
12
+ }
13
+ if (data.color !== undefined) {
14
+ this.color = AnimatableColor.create(this.color, data.color);
15
+ }
16
+ if (data.fill !== undefined) {
17
+ this.fill ??= new Fill();
18
+ this.fill.load(data.fill);
19
+ }
20
+ if (data.stroke !== undefined) {
21
+ this.stroke ??= new Stroke();
22
+ this.stroke.load(data.stroke);
23
+ }
24
+ }
25
+ }
@@ -1,28 +1,28 @@
1
1
  import { deepExtend, executeOnSingleOrMultiple } from "../../../Utils/Utils.js";
2
2
  import { isArray, isNull } from "../../../Utils/TypeUtils.js";
3
+ import { AnimatableColor } from "../AnimatableColor.js";
3
4
  import { Effect } from "./Effect/Effect.js";
4
5
  import { Fill } from "./Fill.js";
5
6
  import { Move } from "./Move/Move.js";
6
7
  import { Opacity } from "./Opacity/Opacity.js";
8
+ import { Paint } from "./Paint.js";
7
9
  import { ParticlesBounce } from "./Bounce/ParticlesBounce.js";
8
10
  import { ParticlesNumber } from "./Number/ParticlesNumber.js";
9
11
  import { Shape } from "./Shape/Shape.js";
10
12
  import { Size } from "./Size/Size.js";
11
- import { Stroke } from "./Stroke.js";
12
13
  import { ZIndex } from "./ZIndex/ZIndex.js";
13
14
  export class ParticlesOptions {
14
15
  bounce;
15
16
  effect;
16
- fill;
17
17
  groups;
18
18
  move;
19
19
  number;
20
20
  opacity;
21
+ paint;
21
22
  palette;
22
23
  reduceDuplicates;
23
24
  shape;
24
25
  size;
25
- stroke;
26
26
  zIndex;
27
27
  _container;
28
28
  _pluginManager;
@@ -31,15 +31,18 @@ export class ParticlesOptions {
31
31
  this._container = container;
32
32
  this.bounce = new ParticlesBounce();
33
33
  this.effect = new Effect();
34
- this.fill = new Fill();
35
34
  this.groups = {};
36
35
  this.move = new Move();
37
36
  this.number = new ParticlesNumber();
38
37
  this.opacity = new Opacity();
38
+ this.paint = new Paint();
39
+ this.paint.color = new AnimatableColor();
40
+ this.paint.color.value = "#fff";
41
+ this.paint.fill = new Fill();
42
+ this.paint.fill.enable = true;
39
43
  this.reduceDuplicates = false;
40
44
  this.shape = new Shape();
41
45
  this.size = new Size();
42
- this.stroke = new Stroke();
43
46
  this.zIndex = new ZIndex();
44
47
  }
45
48
  load(data) {
@@ -69,25 +72,26 @@ export class ParticlesOptions {
69
72
  this.move.load(data.move);
70
73
  this.number.load(data.number);
71
74
  this.opacity.load(data.opacity);
75
+ const paintToLoad = data.paint;
76
+ if (paintToLoad) {
77
+ if (isArray(paintToLoad)) {
78
+ this.paint = executeOnSingleOrMultiple(paintToLoad, t => {
79
+ const tmp = new Paint();
80
+ tmp.load(t);
81
+ return tmp;
82
+ });
83
+ }
84
+ else if (isArray(this.paint)) {
85
+ this.paint = new Paint();
86
+ this.paint.load(paintToLoad);
87
+ }
88
+ else {
89
+ this.paint.load(paintToLoad);
90
+ }
91
+ }
72
92
  this.shape.load(data.shape);
73
93
  this.size.load(data.size);
74
94
  this.zIndex.load(data.zIndex);
75
- const fillToLoad = data.fill;
76
- if (fillToLoad) {
77
- this.fill = executeOnSingleOrMultiple(fillToLoad, t => {
78
- const tmp = new Fill();
79
- tmp.load(t);
80
- return tmp;
81
- });
82
- }
83
- const strokeToLoad = data.stroke;
84
- if (strokeToLoad) {
85
- this.stroke = executeOnSingleOrMultiple(strokeToLoad, t => {
86
- const tmp = new Stroke();
87
- tmp.load(t);
88
- return tmp;
89
- });
90
- }
91
95
  if (this._container) {
92
96
  for (const plugin of this._pluginManager.plugins) {
93
97
  if (plugin.loadParticlesOptions) {
@@ -109,38 +113,40 @@ export class ParticlesOptions {
109
113
  if (!paletteData) {
110
114
  return;
111
115
  }
112
- const paletteColors = paletteData.colors, paletteFill = paletteColors.fill, paletteStroke = paletteColors.stroke;
113
- let paletteFillObj = undefined;
114
- if (paletteFill) {
115
- paletteFillObj = {
116
- color: {
117
- value: paletteFill.value,
118
- },
119
- enable: paletteFill.enable,
120
- };
121
- }
122
- let paletteStrokeObj = undefined;
123
- if (paletteStroke) {
124
- if (isArray(paletteStroke)) {
125
- paletteStrokeObj = paletteStroke.map(s => ({
116
+ const paletteColors = paletteData.colors, defaultPaintStrokeWidth = 0, defaultPaintVariantsLength = 1, firstPaintVariantIndex = 0, defaultPalettePaintVariant = {}, colorVariants = isArray(paletteColors) ? paletteColors : [paletteColors], palettePaintVariants = colorVariants.flatMap(variant => {
117
+ const paletteFill = variant.fill, paletteStroke = variant.stroke, fillPart = paletteFill
118
+ ? {
126
119
  color: {
127
- value: s.value,
120
+ value: paletteFill.value,
128
121
  },
129
- width: s.width,
130
- }));
131
- }
132
- else {
133
- paletteStrokeObj = {
134
- color: {
135
- value: paletteStroke.value,
122
+ enable: paletteFill.enable,
123
+ opacity: paletteFill.opacity,
124
+ }
125
+ : undefined;
126
+ if (!paletteStroke) {
127
+ return [
128
+ {
129
+ fill: fillPart,
136
130
  },
137
- width: paletteStroke.width,
138
- };
131
+ ];
139
132
  }
140
- }
133
+ return [
134
+ {
135
+ fill: fillPart,
136
+ stroke: {
137
+ color: {
138
+ value: paletteStroke.value,
139
+ },
140
+ opacity: paletteStroke.opacity,
141
+ width: paletteStroke.width || defaultPaintStrokeWidth,
142
+ },
143
+ },
144
+ ];
145
+ }), palettePaint = palettePaintVariants.length > defaultPaintVariantsLength
146
+ ? palettePaintVariants
147
+ : (palettePaintVariants[firstPaintVariantIndex] ?? defaultPalettePaintVariant);
141
148
  this.load({
142
- fill: paletteFillObj,
143
- stroke: paletteStrokeObj,
149
+ paint: palettePaint,
144
150
  blend: {
145
151
  enable: true,
146
152
  mode: paletteData.blendMode,
@@ -88,12 +88,12 @@ export function drawShape(drawer, data) {
88
88
  if (particle.shapeClose) {
89
89
  context.closePath();
90
90
  }
91
- if (stroke) {
92
- context.stroke();
93
- }
94
91
  if (fill) {
95
92
  context.fill();
96
93
  }
94
+ if (stroke) {
95
+ context.stroke();
96
+ }
97
97
  }
98
98
  export function drawShapeAfterDraw(drawer, data) {
99
99
  if (!drawer?.afterDraw) {
@@ -1,22 +1,39 @@
1
1
  const errorPrefix = "tsParticles - Error";
2
- const _logger = {
3
- debug: console.debug,
4
- error: (message, optionalParams) => {
5
- console.error(`${errorPrefix} - ${message}`, optionalParams);
2
+ const wrap = (fn) => (...args) => {
3
+ fn(...args);
4
+ }, _logger = {
5
+ debug: wrap(console.debug),
6
+ error: (message, ...optionalParams) => {
7
+ console.error(`${errorPrefix} - ${message}`, ...optionalParams);
6
8
  },
7
- info: console.info,
8
- log: console.log,
9
- trace: console.trace,
10
- verbose: console.log,
11
- warning: console.warn,
9
+ info: wrap(console.info),
10
+ log: wrap(console.log),
11
+ trace: wrap(console.trace),
12
+ verbose: wrap(console.log),
13
+ warning: wrap(console.warn),
12
14
  };
13
15
  export function setLogger(logger) {
14
- _logger.debug = logger.debug;
15
- _logger.error = logger.error;
16
- _logger.info = logger.info;
17
- _logger.log = logger.log;
18
- _logger.verbose = logger.verbose;
19
- _logger.warning = logger.warning;
16
+ if (logger.debug) {
17
+ _logger.debug = wrap(logger.debug);
18
+ }
19
+ if (logger.error) {
20
+ _logger.error = wrap(logger.error);
21
+ }
22
+ if (logger.info) {
23
+ _logger.info = wrap(logger.info);
24
+ }
25
+ if (logger.log) {
26
+ _logger.log = wrap(logger.log);
27
+ }
28
+ if (logger.trace) {
29
+ _logger.trace = wrap(logger.trace);
30
+ }
31
+ if (logger.verbose) {
32
+ _logger.verbose = wrap(logger.verbose);
33
+ }
34
+ if (logger.warning) {
35
+ _logger.warning = wrap(logger.warning);
36
+ }
20
37
  }
21
38
  export function getLogger() {
22
39
  return _logger;
@@ -405,6 +405,7 @@ function computeFullScreenStyle(zIndex) {
405
405
  "z-index": zIndex.toString(radix),
406
406
  top: "0",
407
407
  left: "0",
408
+ "pointer-events": "none",
408
409
  };
409
410
  for (const key in style) {
410
411
  const value = style[key];
package/cjs/browser.js ADDED
@@ -0,0 +1,5 @@
1
+ import { tsParticles } from "./index.js";
2
+ const globalObject = globalThis;
3
+ globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
4
+ globalObject.tsParticles = tsParticles;
5
+ export * from "./index.js";
package/cjs/exports.js CHANGED
@@ -28,6 +28,7 @@ export * from "./Options/Classes/Particles/Bounce/ParticlesBounce.js";
28
28
  export * from "./Options/Classes/Particles/Bounce/ParticlesBounceFactor.js";
29
29
  export * from "./Options/Classes/Particles/ParticlesOptions.js";
30
30
  export * from "./Options/Classes/Particles/Fill.js";
31
+ export * from "./Options/Classes/Particles/Paint.js";
31
32
  export * from "./Options/Classes/Particles/Stroke.js";
32
33
  export * from "./Options/Classes/Particles/Move/Move.js";
33
34
  export * from "./Options/Classes/Particles/Move/MoveAngle.js";
package/cjs/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { initEngine } from "./initEngine.js";
2
2
  const tsParticles = initEngine();
3
- globalThis.tsParticles = tsParticles;
4
3
  export * from "./exports.js";
5
4
  export { tsParticles };