@tsparticles/stencil 4.1.2 → 4.2.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 (29) hide show
  1. package/README.md +13 -0
  2. package/dist/cjs/{Container-BB03Liy1.js → Container-CGxn4Tv3.js} +693 -1038
  3. package/dist/cjs/{index-WCJ4NcqE.js → index-7q-LddLf.js} +57 -160
  4. package/dist/cjs/{index-B2lLThjb.js → index-BjS63OiI.js} +95 -5
  5. package/dist/cjs/index.cjs.js +1 -1
  6. package/dist/cjs/loader.cjs.js +2 -2
  7. package/dist/cjs/stencil-particles.cjs.entry.js +23 -6
  8. package/dist/cjs/tsparticlesstencil.cjs.js +2 -2
  9. package/dist/collection/components/stencil-particles/stencil-particles.js +83 -4
  10. package/dist/esm/{Container-C5hHCYio.js → Container-BWWTh10Z.js} +693 -1038
  11. package/dist/esm/{index-DKFk70aj.js → index-PhwiK2_P.js} +95 -6
  12. package/dist/esm/{index-DYnEUqIm.js → index-aPxdqzSw.js} +57 -160
  13. package/dist/esm/index.js +1 -1
  14. package/dist/esm/loader.js +3 -3
  15. package/dist/esm/stencil-particles.entry.js +23 -6
  16. package/dist/esm/tsparticlesstencil.js +3 -3
  17. package/dist/tsparticlesstencil/index.esm.js +1 -1
  18. package/dist/tsparticlesstencil/p-FNL2LsWF.js +1 -0
  19. package/dist/tsparticlesstencil/p-PBQ5N1xQ.js +1 -0
  20. package/dist/tsparticlesstencil/p-PhwiK2_P.js +2 -0
  21. package/dist/tsparticlesstencil/p-e16c4912.entry.js +1 -0
  22. package/dist/tsparticlesstencil/tsparticlesstencil.esm.js +1 -1
  23. package/dist/types/components/stencil-particles/stencil-particles.d.ts +6 -2
  24. package/dist/types/components.d.ts +24 -2
  25. package/package.json +8 -7
  26. package/dist/tsparticlesstencil/p-4488fb9d.entry.js +0 -1
  27. package/dist/tsparticlesstencil/p-C8gVqIeD.js +0 -1
  28. package/dist/tsparticlesstencil/p-DKFk70aj.js +0 -2
  29. package/dist/tsparticlesstencil/p-h0XxhONB.js +0 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-WCJ4NcqE.js');
3
+ var index = require('./index-7q-LddLf.js');
4
4
 
5
5
  class BaseRange {
6
6
  position;
@@ -75,93 +75,86 @@ class Rectangle extends BaseRange {
75
75
  }
76
76
  }
77
77
 
78
- class AnimationOptions {
79
- count;
80
- decay;
81
- delay;
82
- enable;
83
- speed;
84
- sync;
85
- constructor() {
86
- this.count = 0;
87
- this.enable = false;
88
- this.speed = 1;
89
- this.decay = 0;
90
- this.delay = 0;
91
- this.sync = false;
92
- }
78
+ class OptionLoader {
93
79
  load(data) {
94
80
  if (index.isNull(data)) {
95
81
  return;
96
82
  }
97
- if (data.count !== undefined) {
98
- this.count = index.setRangeValue(data.count);
99
- }
100
- if (data.enable !== undefined) {
101
- this.enable = data.enable;
102
- }
103
- if (data.speed !== undefined) {
104
- this.speed = index.setRangeValue(data.speed);
105
- }
106
- if (data.decay !== undefined) {
107
- this.decay = index.setRangeValue(data.decay);
108
- }
109
- if (data.delay !== undefined) {
110
- this.delay = index.setRangeValue(data.delay);
111
- }
112
- if (data.sync !== undefined) {
113
- this.sync = data.sync;
114
- }
83
+ this.doLoad(data);
84
+ }
85
+ }
86
+ function loadOptions(options, ...sourceOptionsArr) {
87
+ for (const sourceOptions of sourceOptionsArr) {
88
+ options.load(sourceOptions);
89
+ }
90
+ }
91
+
92
+ function loadProperty(obj, key, value) {
93
+ if (value !== undefined) {
94
+ obj[key] = value;
95
+ }
96
+ }
97
+ function loadRangeProperty(obj, key, value) {
98
+ if (value !== undefined) {
99
+ obj[key] = index.setRangeValue(value);
100
+ }
101
+ }
102
+ function loadLazyProperty(obj, key, value, factory) {
103
+ if (value !== undefined) {
104
+ const objRecord = obj;
105
+ objRecord[key] ??= factory();
106
+ objRecord[key].load(value);
107
+ }
108
+ }
109
+
110
+ class AnimationOptions extends OptionLoader {
111
+ count = 0;
112
+ decay = 0;
113
+ delay = 0;
114
+ enable = false;
115
+ speed = 1;
116
+ sync = false;
117
+ doLoad(data) {
118
+ loadRangeProperty(this, "count", data.count);
119
+ loadProperty(this, "enable", data.enable);
120
+ loadRangeProperty(this, "speed", data.speed);
121
+ loadRangeProperty(this, "decay", data.decay);
122
+ loadRangeProperty(this, "delay", data.delay);
123
+ loadProperty(this, "sync", data.sync);
115
124
  }
116
125
  }
117
126
 
118
127
  class ColorAnimation extends AnimationOptions {
119
128
  max;
120
129
  min;
121
- offset;
130
+ offset = 0;
131
+ sync = true;
122
132
  constructor(min, max) {
123
133
  super();
124
134
  this.min = min;
125
135
  this.max = max;
126
- this.offset = 0;
127
- this.sync = true;
128
136
  }
129
- load(data) {
130
- super.load(data);
131
- if (index.isNull(data)) {
132
- return;
133
- }
134
- if (data.max !== undefined) {
135
- this.max = data.max;
136
- }
137
- if (data.min !== undefined) {
138
- this.min = data.min;
139
- }
140
- if (data.offset !== undefined) {
141
- this.offset = index.setRangeValue(data.offset);
142
- }
137
+ doLoad(data) {
138
+ super.doLoad(data);
139
+ loadProperty(this, "max", data.max);
140
+ loadProperty(this, "min", data.min);
141
+ loadRangeProperty(this, "offset", data.offset);
143
142
  }
144
143
  }
145
144
 
146
- class HslAnimation {
145
+ class HslAnimation extends OptionLoader {
147
146
  h = new ColorAnimation(index.hMin, index.hMax);
148
147
  l = new ColorAnimation(index.lMin, index.lMax);
149
148
  s = new ColorAnimation(index.sMin, index.sMax);
150
- load(data) {
151
- if (index.isNull(data)) {
152
- return;
153
- }
149
+ doLoad(data) {
154
150
  this.h.load(data.h);
155
151
  this.s.load(data.s);
156
152
  this.l.load(data.l);
157
153
  }
158
154
  }
159
155
 
160
- class OptionsColor {
161
- value;
162
- constructor() {
163
- this.value = "";
164
- }
156
+ class OptionsColor extends OptionLoader {
157
+ value = "";
165
158
  static create(source, data) {
166
159
  const color = new OptionsColor();
167
160
  color.load(source);
@@ -175,10 +168,7 @@ class OptionsColor {
175
168
  }
176
169
  return color;
177
170
  }
178
- load(data) {
179
- if (index.isNull(data)) {
180
- return;
181
- }
171
+ doLoad(data) {
182
172
  if (!index.isNull(data.value)) {
183
173
  this.value = data.value;
184
174
  }
@@ -186,11 +176,7 @@ class OptionsColor {
186
176
  }
187
177
 
188
178
  class AnimatableColor extends OptionsColor {
189
- animation;
190
- constructor() {
191
- super();
192
- this.animation = new HslAnimation();
193
- }
179
+ animation = new HslAnimation();
194
180
  static create(source, data) {
195
181
  const color = new AnimatableColor();
196
182
  color.load(source);
@@ -204,11 +190,8 @@ class AnimatableColor extends OptionsColor {
204
190
  }
205
191
  return color;
206
192
  }
207
- load(data) {
208
- super.load(data);
209
- if (index.isNull(data)) {
210
- return;
211
- }
193
+ doLoad(data) {
194
+ super.doLoad(data);
212
195
  const colorAnimation = data.animation;
213
196
  if (colorAnimation !== undefined) {
214
197
  if (colorAnimation.enable === undefined) {
@@ -221,100 +204,53 @@ class AnimatableColor extends OptionsColor {
221
204
  }
222
205
  }
223
206
 
224
- class Background {
207
+ class Background extends OptionLoader {
225
208
  color;
226
- image;
227
- opacity;
228
- position;
229
- repeat;
230
- size;
209
+ image = "";
210
+ opacity = 1;
211
+ position = "";
212
+ repeat = "";
213
+ size = "";
231
214
  constructor() {
215
+ super();
232
216
  this.color = new OptionsColor();
233
217
  this.color.value = "";
234
- this.image = "";
235
- this.position = "";
236
- this.repeat = "";
237
- this.size = "";
238
- this.opacity = 1;
239
218
  }
240
- load(data) {
241
- if (index.isNull(data)) {
242
- return;
243
- }
219
+ doLoad(data) {
244
220
  if (data.color !== undefined) {
245
221
  this.color = OptionsColor.create(this.color, data.color);
246
222
  }
247
- if (data.image !== undefined) {
248
- this.image = data.image;
249
- }
250
- if (data.position !== undefined) {
251
- this.position = data.position;
252
- }
253
- if (data.repeat !== undefined) {
254
- this.repeat = data.repeat;
255
- }
256
- if (data.size !== undefined) {
257
- this.size = data.size;
258
- }
259
- if (data.opacity !== undefined) {
260
- this.opacity = data.opacity;
261
- }
223
+ loadProperty(this, "image", data.image);
224
+ loadProperty(this, "position", data.position);
225
+ loadProperty(this, "repeat", data.repeat);
226
+ loadProperty(this, "size", data.size);
227
+ loadProperty(this, "opacity", data.opacity);
262
228
  }
263
229
  }
264
230
 
265
- class FullScreen {
266
- enable;
267
- zIndex;
268
- constructor() {
269
- this.enable = true;
270
- this.zIndex = 0;
271
- }
272
- load(data) {
273
- if (index.isNull(data)) {
274
- return;
275
- }
276
- if (data.enable !== undefined) {
277
- this.enable = data.enable;
278
- }
279
- if (data.zIndex !== undefined) {
280
- this.zIndex = data.zIndex;
281
- }
231
+ class FullScreen extends OptionLoader {
232
+ enable = true;
233
+ zIndex = 0;
234
+ doLoad(data) {
235
+ loadProperty(this, "enable", data.enable);
236
+ loadProperty(this, "zIndex", data.zIndex);
282
237
  }
283
238
  }
284
239
 
285
- class ResizeEvent {
286
- delay;
287
- enable;
288
- constructor() {
289
- this.delay = 0.5;
290
- this.enable = true;
291
- }
292
- load(data) {
293
- if (index.isNull(data)) {
294
- return;
295
- }
296
- if (data.delay !== undefined) {
297
- this.delay = data.delay;
298
- }
299
- if (data.enable !== undefined) {
300
- this.enable = data.enable;
301
- }
240
+ class ResizeEvent extends OptionLoader {
241
+ delay = 0.5;
242
+ enable = true;
243
+ doLoad(data) {
244
+ loadProperty(this, "delay", data.delay);
245
+ loadProperty(this, "enable", data.enable);
302
246
  }
303
247
  }
304
248
 
305
- class Effect {
306
- close;
307
- options;
308
- type;
309
- constructor() {
310
- this.close = true;
311
- this.options = {};
312
- this.type = [];
313
- }
314
- load(data) {
315
- if (index.isNull(data)) {
316
- return;
317
- }
249
+ class Effect extends OptionLoader {
250
+ close = true;
251
+ options = {};
252
+ type = [];
253
+ doLoad(data) {
318
254
  const options = data.options;
319
255
  if (options !== undefined) {
320
256
  for (const effect in options) {
@@ -324,157 +260,78 @@ class Effect {
324
260
  }
325
261
  }
326
262
  }
327
- if (data.close !== undefined) {
328
- this.close = data.close;
329
- }
330
- if (data.type !== undefined) {
331
- this.type = data.type;
332
- }
263
+ loadProperty(this, "close", data.close);
264
+ loadProperty(this, "type", data.type);
333
265
  }
334
266
  }
335
267
 
336
- class Fill {
268
+ class Fill extends OptionLoader {
337
269
  color;
338
- enable;
339
- opacity;
340
- constructor() {
341
- this.enable = true;
342
- this.opacity = 1;
343
- }
344
- load(data) {
345
- if (index.isNull(data)) {
346
- return;
347
- }
270
+ enable = true;
271
+ opacity = 1;
272
+ doLoad(data) {
348
273
  if (data.color !== undefined) {
349
274
  this.color = AnimatableColor.create(this.color, data.color);
350
275
  }
351
- if (data.enable !== undefined) {
352
- this.enable = data.enable;
353
- }
354
- if (data.opacity !== undefined) {
355
- this.opacity = index.setRangeValue(data.opacity);
356
- }
276
+ loadProperty(this, "enable", data.enable);
277
+ loadRangeProperty(this, "opacity", data.opacity);
357
278
  }
358
279
  }
359
280
 
360
- class MoveAngle {
361
- offset;
362
- value;
363
- constructor() {
364
- this.offset = 0;
365
- this.value = 90;
366
- }
367
- load(data) {
368
- if (index.isNull(data)) {
369
- return;
370
- }
371
- if (data.offset !== undefined) {
372
- this.offset = index.setRangeValue(data.offset);
373
- }
374
- if (data.value !== undefined) {
375
- this.value = index.setRangeValue(data.value);
376
- }
281
+ class MoveAngle extends OptionLoader {
282
+ offset = 0;
283
+ value = 90;
284
+ doLoad(data) {
285
+ loadRangeProperty(this, "offset", data.offset);
286
+ loadRangeProperty(this, "value", data.value);
377
287
  }
378
288
  }
379
289
 
380
- class MoveCenter {
381
- mode;
382
- radius;
383
- x;
384
- y;
385
- constructor() {
386
- this.x = 50;
387
- this.y = 50;
388
- this.mode = index.PixelMode.percent;
389
- this.radius = 0;
390
- }
391
- load(data) {
392
- if (index.isNull(data)) {
393
- return;
394
- }
395
- if (data.x !== undefined) {
396
- this.x = data.x;
397
- }
398
- if (data.y !== undefined) {
399
- this.y = data.y;
400
- }
401
- if (data.mode !== undefined) {
402
- this.mode = data.mode;
403
- }
404
- if (data.radius !== undefined) {
405
- this.radius = data.radius;
406
- }
290
+ class MoveCenter extends OptionLoader {
291
+ mode = index.PixelMode.percent;
292
+ radius = 0;
293
+ x = 50;
294
+ y = 50;
295
+ doLoad(data) {
296
+ loadProperty(this, "x", data.x);
297
+ loadProperty(this, "y", data.y);
298
+ loadProperty(this, "mode", data.mode);
299
+ loadProperty(this, "radius", data.radius);
407
300
  }
408
301
  }
409
302
 
410
- class MoveGravity {
411
- acceleration;
412
- enable;
413
- inverse;
414
- maxSpeed;
415
- constructor() {
416
- this.acceleration = 9.81;
417
- this.enable = false;
418
- this.inverse = false;
419
- this.maxSpeed = 50;
420
- }
421
- load(data) {
422
- if (index.isNull(data)) {
423
- return;
424
- }
425
- if (data.acceleration !== undefined) {
426
- this.acceleration = index.setRangeValue(data.acceleration);
427
- }
428
- if (data.enable !== undefined) {
429
- this.enable = data.enable;
430
- }
431
- if (data.inverse !== undefined) {
432
- this.inverse = data.inverse;
433
- }
434
- if (data.maxSpeed !== undefined) {
435
- this.maxSpeed = index.setRangeValue(data.maxSpeed);
436
- }
303
+ class MoveGravity extends OptionLoader {
304
+ acceleration = 9.81;
305
+ enable = false;
306
+ inverse = false;
307
+ maxSpeed = 50;
308
+ doLoad(data) {
309
+ loadRangeProperty(this, "acceleration", data.acceleration);
310
+ loadProperty(this, "enable", data.enable);
311
+ loadProperty(this, "inverse", data.inverse);
312
+ loadRangeProperty(this, "maxSpeed", data.maxSpeed);
437
313
  }
438
314
  }
439
315
 
440
- class ValueWithRandom {
441
- value;
442
- constructor() {
443
- this.value = 0;
444
- }
445
- load(data) {
446
- if (index.isNull(data)) {
447
- return;
448
- }
316
+ class ValueWithRandom extends OptionLoader {
317
+ value = 0;
318
+ doLoad(data) {
449
319
  if (!index.isNull(data.value)) {
450
320
  this.value = index.setRangeValue(data.value);
451
321
  }
452
322
  }
453
323
  }
454
324
 
455
- class MovePath {
456
- clamp;
457
- delay;
458
- enable;
325
+ class MovePath extends OptionLoader {
326
+ clamp = true;
327
+ delay = new ValueWithRandom();
328
+ enable = false;
459
329
  generator;
460
- options;
461
- constructor() {
462
- this.clamp = true;
463
- this.delay = new ValueWithRandom();
464
- this.enable = false;
465
- this.options = {};
466
- }
467
- load(data) {
468
- if (index.isNull(data)) {
469
- return;
470
- }
471
- if (data.clamp !== undefined) {
472
- this.clamp = data.clamp;
473
- }
330
+ options = {};
331
+ doLoad(data) {
332
+ loadProperty(this, "clamp", data.clamp);
474
333
  this.delay.load(data.delay);
475
- if (data.enable !== undefined) {
476
- this.enable = data.enable;
477
- }
334
+ loadProperty(this, "enable", data.enable);
478
335
  this.generator = data.generator;
479
336
  if (data.options) {
480
337
  this.options = index.deepExtend(this.options, data.options);
@@ -482,19 +339,13 @@ class MovePath {
482
339
  }
483
340
  }
484
341
 
485
- class OutModes {
342
+ class OutModes extends OptionLoader {
486
343
  bottom;
487
- default;
344
+ default = index.OutMode.out;
488
345
  left;
489
346
  right;
490
347
  top;
491
- constructor() {
492
- this.default = index.OutMode.out;
493
- }
494
- load(data) {
495
- if (index.isNull(data)) {
496
- return;
497
- }
348
+ doLoad(data) {
498
349
  if (data.default !== undefined) {
499
350
  this.default = data.default;
500
351
  }
@@ -505,79 +356,42 @@ class OutModes {
505
356
  }
506
357
  }
507
358
 
508
- class Spin {
509
- acceleration;
510
- enable;
359
+ class Spin extends OptionLoader {
360
+ acceleration = 0;
361
+ enable = false;
511
362
  position;
512
- constructor() {
513
- this.acceleration = 0;
514
- this.enable = false;
515
- }
516
- load(data) {
517
- if (index.isNull(data)) {
518
- return;
519
- }
520
- if (data.acceleration !== undefined) {
521
- this.acceleration = index.setRangeValue(data.acceleration);
522
- }
523
- if (data.enable !== undefined) {
524
- this.enable = data.enable;
525
- }
363
+ doLoad(data) {
364
+ loadRangeProperty(this, "acceleration", data.acceleration);
365
+ loadProperty(this, "enable", data.enable);
526
366
  if (data.position) {
527
367
  this.position = index.deepExtend({}, data.position);
528
368
  }
529
369
  }
530
370
  }
531
371
 
532
- class Move {
533
- angle;
534
- center;
535
- decay;
536
- direction;
537
- distance;
538
- drift;
539
- enable;
540
- gravity;
541
- outModes;
542
- path;
543
- random;
544
- size;
545
- speed;
546
- spin;
547
- straight;
548
- vibrate;
549
- warp;
550
- constructor() {
551
- this.angle = new MoveAngle();
552
- this.center = new MoveCenter();
553
- this.decay = 0;
554
- this.distance = {};
555
- this.direction = index.MoveDirection.none;
556
- this.drift = 0;
557
- this.enable = false;
558
- this.gravity = new MoveGravity();
559
- this.path = new MovePath();
560
- this.outModes = new OutModes();
561
- this.random = false;
562
- this.size = false;
563
- this.speed = 2;
564
- this.spin = new Spin();
565
- this.straight = false;
566
- this.vibrate = false;
567
- this.warp = false;
568
- }
569
- load(data) {
570
- if (index.isNull(data)) {
571
- return;
572
- }
372
+ class Move extends OptionLoader {
373
+ angle = new MoveAngle();
374
+ center = new MoveCenter();
375
+ decay = 0;
376
+ direction = index.MoveDirection.none;
377
+ distance = {};
378
+ drift = 0;
379
+ enable = false;
380
+ gravity = new MoveGravity();
381
+ outModes = new OutModes();
382
+ path = new MovePath();
383
+ random = false;
384
+ size = false;
385
+ speed = 2;
386
+ spin = new Spin();
387
+ straight = false;
388
+ vibrate = false;
389
+ warp = false;
390
+ doLoad(data) {
573
391
  this.angle.load(index.isNumber(data.angle) ? { value: data.angle } : data.angle);
574
392
  this.center.load(data.center);
575
- if (data.decay !== undefined) {
576
- this.decay = index.setRangeValue(data.decay);
577
- }
578
- if (data.direction !== undefined) {
579
- this.direction = data.direction;
580
- }
393
+ loadRangeProperty(this, "decay", data.decay);
394
+ loadProperty(this, "direction", data.direction);
581
395
  if (data.distance !== undefined) {
582
396
  this.distance = index.isNumber(data.distance)
583
397
  ? {
@@ -586,12 +400,8 @@ class Move {
586
400
  }
587
401
  : { ...data.distance };
588
402
  }
589
- if (data.drift !== undefined) {
590
- this.drift = index.setRangeValue(data.drift);
591
- }
592
- if (data.enable !== undefined) {
593
- this.enable = data.enable;
594
- }
403
+ loadRangeProperty(this, "drift", data.drift);
404
+ loadProperty(this, "enable", data.enable);
595
405
  this.gravity.load(data.gravity);
596
406
  const outModes = data.outModes;
597
407
  if (outModes !== undefined) {
@@ -605,177 +415,91 @@ class Move {
605
415
  }
606
416
  }
607
417
  this.path.load(data.path);
608
- if (data.random !== undefined) {
609
- this.random = data.random;
610
- }
611
- if (data.size !== undefined) {
612
- this.size = data.size;
613
- }
614
- if (data.speed !== undefined) {
615
- this.speed = index.setRangeValue(data.speed);
616
- }
418
+ loadProperty(this, "random", data.random);
419
+ loadProperty(this, "size", data.size);
420
+ loadRangeProperty(this, "speed", data.speed);
617
421
  this.spin.load(data.spin);
618
- if (data.straight !== undefined) {
619
- this.straight = data.straight;
620
- }
621
- if (data.vibrate !== undefined) {
622
- this.vibrate = data.vibrate;
623
- }
624
- if (data.warp !== undefined) {
625
- this.warp = data.warp;
626
- }
422
+ loadProperty(this, "straight", data.straight);
423
+ loadProperty(this, "vibrate", data.vibrate);
424
+ loadProperty(this, "warp", data.warp);
627
425
  }
628
426
  }
629
427
 
630
- class Stroke {
428
+ class Stroke extends OptionLoader {
631
429
  color;
632
430
  opacity;
633
- width;
634
- constructor() {
635
- this.width = 0;
636
- }
637
- load(data) {
638
- if (index.isNull(data)) {
639
- return;
640
- }
431
+ width = 0;
432
+ doLoad(data) {
641
433
  if (data.color !== undefined) {
642
434
  this.color = AnimatableColor.create(this.color, data.color);
643
435
  }
644
- if (data.width !== undefined) {
645
- this.width = index.setRangeValue(data.width);
646
- }
647
- if (data.opacity !== undefined) {
648
- this.opacity = index.setRangeValue(data.opacity);
649
- }
436
+ loadRangeProperty(this, "width", data.width);
437
+ loadRangeProperty(this, "opacity", data.opacity);
650
438
  }
651
439
  }
652
440
 
653
- class Paint {
441
+ class Paint extends OptionLoader {
654
442
  color;
655
443
  fill;
656
444
  stroke;
657
- load(data) {
658
- if (index.isNull(data)) {
659
- return;
660
- }
445
+ doLoad(data) {
661
446
  if (data.color !== undefined) {
662
447
  this.color = AnimatableColor.create(this.color, data.color);
663
448
  }
664
- if (data.fill !== undefined) {
665
- this.fill ??= new Fill();
666
- this.fill.load(data.fill);
667
- }
668
- if (data.stroke !== undefined) {
669
- this.stroke ??= new Stroke();
670
- this.stroke.load(data.stroke);
671
- }
449
+ loadLazyProperty(this, "fill", data.fill, () => new Fill());
450
+ loadLazyProperty(this, "stroke", data.stroke, () => new Stroke());
672
451
  }
673
452
  }
674
453
 
675
454
  class ParticlesBounceFactor extends ValueWithRandom {
676
- constructor() {
677
- super();
678
- this.value = 1;
679
- }
455
+ value = 1;
680
456
  }
681
457
 
682
- class ParticlesBounce {
683
- horizontal;
684
- vertical;
685
- constructor() {
686
- this.horizontal = new ParticlesBounceFactor();
687
- this.vertical = new ParticlesBounceFactor();
688
- }
689
- load(data) {
690
- if (index.isNull(data)) {
691
- return;
692
- }
458
+ class ParticlesBounce extends OptionLoader {
459
+ horizontal = new ParticlesBounceFactor();
460
+ vertical = new ParticlesBounceFactor();
461
+ doLoad(data) {
693
462
  this.horizontal.load(data.horizontal);
694
463
  this.vertical.load(data.vertical);
695
464
  }
696
465
  }
697
466
 
698
- class ParticlesDensity {
699
- enable;
700
- height;
701
- width;
702
- constructor() {
703
- this.enable = false;
704
- this.width = 1920;
705
- this.height = 1080;
706
- }
707
- load(data) {
708
- if (index.isNull(data)) {
709
- return;
710
- }
711
- if (data.enable !== undefined) {
712
- this.enable = data.enable;
713
- }
714
- const width = data.width;
715
- if (width !== undefined) {
716
- this.width = width;
717
- }
718
- const height = data.height;
719
- if (height !== undefined) {
720
- this.height = height;
721
- }
467
+ class ParticlesDensity extends OptionLoader {
468
+ enable = false;
469
+ height = 1080;
470
+ width = 1920;
471
+ doLoad(data) {
472
+ loadProperty(this, "enable", data.enable);
473
+ loadProperty(this, "width", data.width);
474
+ loadProperty(this, "height", data.height);
722
475
  }
723
476
  }
724
477
 
725
- class ParticlesNumberLimit {
726
- mode;
727
- value;
728
- constructor() {
729
- this.mode = index.LimitMode.delete;
730
- this.value = 0;
731
- }
732
- load(data) {
733
- if (index.isNull(data)) {
734
- return;
735
- }
736
- if (data.mode !== undefined) {
737
- this.mode = data.mode;
738
- }
739
- if (data.value !== undefined) {
740
- this.value = data.value;
741
- }
478
+ class ParticlesNumberLimit extends OptionLoader {
479
+ mode = index.LimitMode.delete;
480
+ value = 0;
481
+ doLoad(data) {
482
+ loadProperty(this, "mode", data.mode);
483
+ loadProperty(this, "value", data.value);
742
484
  }
743
485
  }
744
486
 
745
- class ParticlesNumber {
746
- density;
747
- limit;
748
- value;
749
- constructor() {
750
- this.density = new ParticlesDensity();
751
- this.limit = new ParticlesNumberLimit();
752
- this.value = 0;
753
- }
754
- load(data) {
755
- if (index.isNull(data)) {
756
- return;
757
- }
487
+ class ParticlesNumber extends OptionLoader {
488
+ density = new ParticlesDensity();
489
+ limit = new ParticlesNumberLimit();
490
+ value = 0;
491
+ doLoad(data) {
758
492
  this.density.load(data.density);
759
493
  this.limit.load(data.limit);
760
- if (data.value !== undefined) {
761
- this.value = data.value;
762
- }
494
+ loadProperty(this, "value", data.value);
763
495
  }
764
496
  }
765
497
 
766
- class Shape {
767
- close;
768
- options;
769
- type;
770
- constructor() {
771
- this.close = true;
772
- this.options = {};
773
- this.type = "circle";
774
- }
775
- load(data) {
776
- if (index.isNull(data)) {
777
- return;
778
- }
498
+ class Shape extends OptionLoader {
499
+ close = true;
500
+ options = {};
501
+ type = "circle";
502
+ doLoad(data) {
779
503
  const options = data.options;
780
504
  if (options !== undefined) {
781
505
  for (const shape in options) {
@@ -785,76 +509,47 @@ class Shape {
785
509
  }
786
510
  }
787
511
  }
788
- if (data.close !== undefined) {
789
- this.close = data.close;
790
- }
791
- if (data.type !== undefined) {
792
- this.type = data.type;
793
- }
512
+ loadProperty(this, "close", data.close);
513
+ loadProperty(this, "type", data.type);
794
514
  }
795
515
  }
796
516
 
797
517
  class ZIndex extends ValueWithRandom {
798
- opacityRate;
799
- sizeRate;
800
- velocityRate;
801
- constructor() {
802
- super();
803
- this.opacityRate = 1;
804
- this.sizeRate = 1;
805
- this.velocityRate = 1;
806
- }
807
- load(data) {
808
- super.load(data);
809
- if (index.isNull(data)) {
810
- return;
811
- }
812
- if (data.opacityRate !== undefined) {
813
- this.opacityRate = data.opacityRate;
814
- }
815
- if (data.sizeRate !== undefined) {
816
- this.sizeRate = data.sizeRate;
817
- }
818
- if (data.velocityRate !== undefined) {
819
- this.velocityRate = data.velocityRate;
820
- }
518
+ opacityRate = 1;
519
+ sizeRate = 1;
520
+ velocityRate = 1;
521
+ doLoad(data) {
522
+ super.doLoad(data);
523
+ loadProperty(this, "opacityRate", data.opacityRate);
524
+ loadProperty(this, "sizeRate", data.sizeRate);
525
+ loadProperty(this, "velocityRate", data.velocityRate);
821
526
  }
822
527
  }
823
528
 
824
- class ParticlesOptions {
825
- bounce;
826
- effect;
827
- groups;
828
- move;
829
- number;
529
+ class ParticlesOptions extends OptionLoader {
530
+ bounce = new ParticlesBounce();
531
+ effect = new Effect();
532
+ groups = {};
533
+ move = new Move();
534
+ number = new ParticlesNumber();
830
535
  paint;
831
536
  palette;
832
- reduceDuplicates;
833
- shape;
834
- zIndex;
537
+ reduceDuplicates = false;
538
+ shape = new Shape();
539
+ zIndex = new ZIndex();
835
540
  #container;
836
541
  #pluginManager;
837
542
  constructor(pluginManager, container) {
543
+ super();
838
544
  this.#pluginManager = pluginManager;
839
545
  this.#container = container;
840
- this.bounce = new ParticlesBounce();
841
- this.effect = new Effect();
842
- this.groups = {};
843
- this.move = new Move();
844
- this.number = new ParticlesNumber();
845
546
  this.paint = new Paint();
846
547
  this.paint.color = new AnimatableColor();
847
548
  this.paint.color.value = "#fff";
848
549
  this.paint.fill = new Fill();
849
550
  this.paint.fill.enable = true;
850
- this.reduceDuplicates = false;
851
- this.shape = new Shape();
852
- this.zIndex = new ZIndex();
853
551
  }
854
- load(data) {
855
- if (index.isNull(data)) {
856
- return;
857
- }
552
+ doLoad(data) {
858
553
  if (data.palette) {
859
554
  this.palette = data.palette;
860
555
  this.#importPalette(this.palette);
@@ -912,7 +607,7 @@ class ParticlesOptions {
912
607
  }
913
608
  }
914
609
  }
915
- #importPalette = (palette) => {
610
+ #importPalette(palette) {
916
611
  const paletteData = this.#pluginManager.getPalette(palette);
917
612
  if (!paletteData) {
918
613
  return;
@@ -956,289 +651,117 @@ class ParticlesOptions {
956
651
  mode: paletteData.blendMode,
957
652
  },
958
653
  });
959
- };
960
- }
961
-
962
- function loadOptions(options, ...sourceOptionsArr) {
963
- for (const sourceOptions of sourceOptionsArr) {
964
- options.load(sourceOptions);
965
654
  }
966
655
  }
656
+
967
657
  function loadParticlesOptions(pluginManager, container, ...sourceOptionsArr) {
968
658
  const options = new ParticlesOptions(pluginManager, container);
969
659
  loadOptions(options, ...sourceOptionsArr);
970
660
  return options;
971
661
  }
972
662
 
973
- class Options {
974
- autoPlay;
663
+ class Options extends OptionLoader {
664
+ autoPlay = true;
975
665
  background;
976
- clear;
977
- defaultThemes;
978
- delay;
979
- detectRetina;
980
- duration;
981
- fpsLimit;
666
+ clear = true;
667
+ defaultThemes = {};
668
+ delay = 0;
669
+ detectRetina = true;
670
+ duration = 0;
671
+ fpsLimit = 120;
982
672
  fullScreen;
983
- hdr;
673
+ hdr = true;
984
674
  key;
985
675
  name;
986
676
  palette;
987
677
  particles;
988
- pauseOnBlur;
989
- pauseOnOutsideViewport;
678
+ pauseOnBlur = true;
679
+ pauseOnOutsideViewport = true;
990
680
  preset;
991
681
  resize;
992
- smooth;
993
- style;
994
- zLayers;
682
+ smooth = false;
683
+ style = {};
684
+ zLayers = 100;
995
685
  #container;
996
686
  #pluginManager;
997
687
  constructor(pluginManager, container) {
688
+ super();
998
689
  this.#pluginManager = pluginManager;
999
690
  this.#container = container;
1000
- this.autoPlay = true;
1001
691
  this.background = new Background();
1002
- this.clear = true;
1003
- this.defaultThemes = {};
1004
- this.delay = 0;
1005
692
  this.fullScreen = new FullScreen();
1006
- this.detectRetina = true;
1007
- this.duration = 0;
1008
- this.fpsLimit = 120;
1009
- this.hdr = true;
1010
693
  this.particles = loadParticlesOptions(this.#pluginManager, this.#container);
1011
- this.pauseOnBlur = true;
1012
- this.pauseOnOutsideViewport = true;
1013
694
  this.resize = new ResizeEvent();
1014
- this.smooth = false;
1015
- this.style = {};
1016
- this.zLayers = 100;
1017
695
  }
1018
- load(data) {
1019
- if (index.isNull(data)) {
1020
- return;
1021
- }
696
+ doLoad(data) {
1022
697
  if (data.preset !== undefined) {
1023
698
  this.preset = data.preset;
1024
699
  index.executeOnSingleOrMultiple(this.preset, preset => {
1025
700
  this.#importPreset(preset);
1026
701
  });
1027
702
  }
1028
- if (data.palette !== undefined) {
1029
- this.palette = data.palette;
1030
- this.#importPalette(this.palette);
1031
- }
1032
- if (data.autoPlay !== undefined) {
1033
- this.autoPlay = data.autoPlay;
1034
- }
1035
- if (data.clear !== undefined) {
1036
- this.clear = data.clear;
1037
- }
1038
- if (data.key !== undefined) {
1039
- this.key = data.key;
1040
- }
1041
- if (data.name !== undefined) {
1042
- this.name = data.name;
1043
- }
1044
- if (data.delay !== undefined) {
1045
- this.delay = index.setRangeValue(data.delay);
1046
- }
1047
- const detectRetina = data.detectRetina;
1048
- if (detectRetina !== undefined) {
1049
- this.detectRetina = detectRetina;
1050
- }
1051
- if (data.duration !== undefined) {
1052
- this.duration = index.setRangeValue(data.duration);
1053
- }
1054
- const fpsLimit = data.fpsLimit;
1055
- if (fpsLimit !== undefined) {
1056
- this.fpsLimit = fpsLimit;
1057
- }
1058
- if (data.hdr !== undefined) {
1059
- this.hdr = data.hdr;
1060
- }
1061
- if (data.pauseOnBlur !== undefined) {
1062
- this.pauseOnBlur = data.pauseOnBlur;
1063
- }
1064
- if (data.pauseOnOutsideViewport !== undefined) {
1065
- this.pauseOnOutsideViewport = data.pauseOnOutsideViewport;
1066
- }
1067
- if (data.zLayers !== undefined) {
1068
- this.zLayers = data.zLayers;
1069
- }
1070
- this.background.load(data.background);
1071
- const fullScreen = data.fullScreen;
1072
- if (index.isBoolean(fullScreen)) {
1073
- this.fullScreen.enable = fullScreen;
1074
- }
1075
- else {
1076
- this.fullScreen.load(fullScreen);
1077
- }
1078
- this.particles.load(data.particles);
1079
- this.resize.load(data.resize);
1080
- this.style = index.deepExtend(this.style, data.style);
1081
- if (data.smooth !== undefined) {
1082
- this.smooth = data.smooth;
1083
- }
1084
- this.#pluginManager.plugins.forEach(plugin => {
1085
- plugin.loadOptions(this.#container, this, data);
1086
- });
1087
- }
1088
- #importPalette = palette => {
1089
- const paletteData = this.#pluginManager.getPalette(palette);
1090
- if (!paletteData) {
1091
- return;
1092
- }
1093
- this.load({
1094
- background: {
1095
- color: paletteData.background,
1096
- },
1097
- blend: {
1098
- enable: true,
1099
- mode: paletteData.blendMode,
1100
- },
1101
- particles: {
1102
- palette,
1103
- },
1104
- });
1105
- };
1106
- #importPreset = preset => {
1107
- this.load(this.#pluginManager.getPreset(preset));
1108
- };
1109
- }
1110
-
1111
- function paintBase(context, dimension, baseColor) {
1112
- context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1113
- context.fillRect(index.originPoint.x, index.originPoint.y, dimension.width, dimension.height);
1114
- }
1115
- function paintImage(context, dimension, image, opacity) {
1116
- if (!image) {
1117
- return;
1118
- }
1119
- const prevAlpha = context.globalAlpha;
1120
- context.globalAlpha = opacity;
1121
- context.drawImage(image, index.originPoint.x, index.originPoint.y, dimension.width, dimension.height);
1122
- context.globalAlpha = prevAlpha;
1123
- }
1124
- function clear(context, dimension) {
1125
- context.clearRect(index.originPoint.x, index.originPoint.y, dimension.width, dimension.height);
1126
- }
1127
- function drawParticle(data) {
1128
- const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = index.defaultZoom, drawPosition = {
1129
- x: pos.x,
1130
- y: pos.y,
1131
- };
1132
- context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1133
- if (colorStyles.fill) {
1134
- context.fillStyle = colorStyles.fill;
1135
- }
1136
- const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? index.minStrokeWidth;
1137
- context.lineWidth = strokeWidth;
1138
- if (colorStyles.stroke) {
1139
- context.strokeStyle = colorStyles.stroke;
1140
- }
1141
- const drawData = {
1142
- context,
1143
- particle,
1144
- radius,
1145
- drawRadius: radius * drawScale,
1146
- opacity,
1147
- delta,
1148
- pixelRatio: container.retina.pixelRatio,
1149
- fill: fillEnabled,
1150
- stroke: strokeWidth > index.minStrokeWidth,
1151
- transformData,
1152
- position: { ...pos },
1153
- drawPosition,
1154
- drawScale,
1155
- };
1156
- for (const plugin of container.plugins) {
1157
- plugin.drawParticleTransform?.(drawData);
1158
- }
1159
- const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
1160
- drawBeforeEffect(effect, drawData);
1161
- drawShapeBeforeDraw(shape, drawData);
1162
- drawShape(shape, drawData);
1163
- drawShapeAfterDraw(shape, drawData);
1164
- drawAfterEffect(effect, drawData);
1165
- context.resetTransform();
1166
- }
1167
- function drawAfterEffect(drawer, data) {
1168
- if (!drawer?.drawAfter) {
1169
- return;
1170
- }
1171
- const { particle } = data;
1172
- if (!particle.effect) {
1173
- return;
1174
- }
1175
- drawer.drawAfter(data);
1176
- }
1177
- function drawBeforeEffect(drawer, data) {
1178
- if (!drawer?.drawBefore) {
1179
- return;
1180
- }
1181
- const { particle } = data;
1182
- if (!particle.effect) {
1183
- return;
1184
- }
1185
- drawer.drawBefore(data);
1186
- }
1187
- function drawShape(drawer, data) {
1188
- if (!drawer) {
1189
- return;
1190
- }
1191
- const { context, fill, particle, stroke } = data;
1192
- if (!particle.shape) {
1193
- return;
1194
- }
1195
- context.beginPath();
1196
- drawer.draw(data);
1197
- if (particle.shapeClose) {
1198
- context.closePath();
1199
- }
1200
- if (fill) {
1201
- context.fill();
1202
- }
1203
- if (stroke) {
1204
- context.stroke();
1205
- }
1206
- }
1207
- function drawShapeAfterDraw(drawer, data) {
1208
- if (!drawer?.afterDraw) {
1209
- return;
1210
- }
1211
- const { particle } = data;
1212
- if (!particle.shape) {
1213
- return;
1214
- }
1215
- drawer.afterDraw(data);
1216
- }
1217
- function drawShapeBeforeDraw(drawer, data) {
1218
- if (!drawer?.beforeDraw) {
1219
- return;
703
+ if (data.palette !== undefined) {
704
+ this.palette = data.palette;
705
+ this.#importPalette(this.palette);
706
+ }
707
+ loadProperty(this, "autoPlay", data.autoPlay);
708
+ loadProperty(this, "clear", data.clear);
709
+ loadProperty(this, "key", data.key);
710
+ loadProperty(this, "name", data.name);
711
+ loadRangeProperty(this, "delay", data.delay);
712
+ loadProperty(this, "detectRetina", data.detectRetina);
713
+ loadRangeProperty(this, "duration", data.duration);
714
+ loadProperty(this, "fpsLimit", data.fpsLimit);
715
+ loadProperty(this, "hdr", data.hdr);
716
+ loadProperty(this, "pauseOnBlur", data.pauseOnBlur);
717
+ loadProperty(this, "pauseOnOutsideViewport", data.pauseOnOutsideViewport);
718
+ loadProperty(this, "zLayers", data.zLayers);
719
+ this.background.load(data.background);
720
+ const fullScreen = data.fullScreen;
721
+ if (index.isBoolean(fullScreen)) {
722
+ this.fullScreen.enable = fullScreen;
723
+ }
724
+ else {
725
+ this.fullScreen.load(fullScreen);
726
+ }
727
+ this.particles.load(data.particles);
728
+ this.resize.load(data.resize);
729
+ this.style = index.deepExtend(this.style, data.style);
730
+ loadProperty(this, "smooth", data.smooth);
731
+ this.#pluginManager.plugins.forEach(plugin => {
732
+ plugin.loadOptions(this.#container, this, data);
733
+ });
1220
734
  }
1221
- const { particle } = data;
1222
- if (!particle.shape) {
1223
- return;
735
+ #importPalette(palette) {
736
+ const paletteData = this.#pluginManager.getPalette(palette);
737
+ if (!paletteData) {
738
+ return;
739
+ }
740
+ this.load({
741
+ background: {
742
+ color: paletteData.background,
743
+ },
744
+ blend: {
745
+ enable: true,
746
+ mode: paletteData.blendMode,
747
+ },
748
+ particles: {
749
+ palette,
750
+ },
751
+ });
1224
752
  }
1225
- drawer.beforeDraw(data);
1226
- }
1227
- function drawParticlePlugin(context, plugin, particle, delta) {
1228
- if (!plugin.drawParticle) {
1229
- return;
753
+ #importPreset(preset) {
754
+ this.load(this.#pluginManager.getPreset(preset));
1230
755
  }
1231
- plugin.drawParticle(context, particle, delta);
1232
756
  }
1233
757
 
1234
- const styleCache = new Map(), maxCacheSize = 1000, firstIndex = 0, rgbFixedPrecision = 2, hslFixedPrecision = 2;
758
+ const styleCache = new Map(), maxStyleCacheSize = 2000, rgbFixedPrecision = 2, hslFixedPrecision = 2, sdrReferenceWhiteNits = 203;
1235
759
  function getCachedStyle(key, generator) {
1236
760
  let cached = styleCache.get(key);
1237
761
  if (!cached) {
1238
762
  cached = generator();
1239
- if (styleCache.size >= maxCacheSize) {
1240
- const keysToDelete = [...styleCache.keys()].slice(firstIndex, maxCacheSize * index.half);
1241
- keysToDelete.forEach(k => styleCache.delete(k));
763
+ if (styleCache.size > maxStyleCacheSize) {
764
+ styleCache.clear();
1242
765
  }
1243
766
  styleCache.set(key, cached);
1244
767
  }
@@ -1341,34 +864,35 @@ function rgbToHsl(color) {
1341
864
  function stringToRgb(pluginManager, input) {
1342
865
  return stringToRgba(pluginManager, input);
1343
866
  }
867
+ function hslChannel(temp1, temp2, temp3) {
868
+ const temp3Min = 0, temp3Max = 1;
869
+ if (temp3 < temp3Min) {
870
+ temp3++;
871
+ }
872
+ if (temp3 > temp3Max) {
873
+ temp3--;
874
+ }
875
+ if (temp3 * index.sextuple < temp3Max) {
876
+ return temp1 + (temp2 - temp1) * index.sextuple * temp3;
877
+ }
878
+ if (temp3 * index.double < temp3Max) {
879
+ return temp2;
880
+ }
881
+ if (temp3 * index.triple < temp3Max * index.double) {
882
+ const temp3Offset = index.double / index.triple;
883
+ return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * index.sextuple;
884
+ }
885
+ return temp1;
886
+ }
1344
887
  function hslToRgb(hsl) {
1345
888
  const h = ((hsl.h % index.hMax) + index.hMax) % index.hMax, s = Math.max(index.sMin, Math.min(index.sMax, hsl.s)), l = Math.max(index.lMin, Math.min(index.lMax, hsl.l)), hNormalized = h / index.hMax, sNormalized = s / index.sMax, lNormalized = l / index.lMax;
1346
889
  if (s === index.sMin) {
1347
890
  const grayscaleValue = Math.round(lNormalized * index.rgbMax);
1348
891
  return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
1349
892
  }
1350
- const channel = (temp1, temp2, temp3) => {
1351
- const temp3Min = 0, temp3Max = 1;
1352
- if (temp3 < temp3Min) {
1353
- temp3++;
1354
- }
1355
- if (temp3 > temp3Max) {
1356
- temp3--;
1357
- }
1358
- if (temp3 * index.sextuple < temp3Max) {
1359
- return temp1 + (temp2 - temp1) * index.sextuple * temp3;
1360
- }
1361
- if (temp3 * index.double < temp3Max) {
1362
- return temp2;
1363
- }
1364
- if (temp3 * index.triple < temp3Max * index.double) {
1365
- const temp3Offset = index.double / index.triple;
1366
- return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * index.sextuple;
1367
- }
1368
- return temp1;
1369
- }, temp1 = lNormalized < index.half
893
+ const temp1 = lNormalized < index.half
1370
894
  ? lNormalized * (index.sNormalizedOffset + sNormalized)
1371
- : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = index.double * lNormalized - temp1, phaseThird = index.phaseNumerator / index.triple, red = Math.min(index.rgbMax, index.rgbMax * channel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(index.rgbMax, index.rgbMax * channel(temp2, temp1, hNormalized)), blue = Math.min(index.rgbMax, index.rgbMax * channel(temp2, temp1, hNormalized - phaseThird));
895
+ : lNormalized + sNormalized - lNormalized * sNormalized, temp2 = index.double * lNormalized - temp1, phaseThird = index.phaseNumerator / index.triple, red = Math.min(index.rgbMax, index.rgbMax * hslChannel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(index.rgbMax, index.rgbMax * hslChannel(temp2, temp1, hNormalized)), blue = Math.min(index.rgbMax, index.rgbMax * hslChannel(temp2, temp1, hNormalized - phaseThird));
1372
896
  return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
1373
897
  }
1374
898
  function getRandomRgbColor(min) {
@@ -1383,21 +907,18 @@ function getStyleFromRgb(color, hdr, opacity) {
1383
907
  const op = opacity ?? index.defaultOpacity, key = `rgb-${color.r.toFixed(rgbFixedPrecision)}-${color.g.toFixed(rgbFixedPrecision)}-${color.b.toFixed(rgbFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1384
908
  return getCachedStyle(key, () => (hdr ? getHdrStyleFromRgb(color, opacity) : getSdrStyleFromRgb(color, opacity)));
1385
909
  }
1386
- function getHdrStyleFromRgb(color, opacity) {
1387
- return `color(display-p3 ${(color.r / index.rgbMax).toString()} ${(color.g / index.rgbMax).toString()} ${(color.b / index.rgbMax).toString()} / ${(opacity ?? index.defaultOpacity).toString()})`;
910
+ function getHdrStyleFromRgb(color, opacity, peakNits = index.maxNits) {
911
+ const headroom = peakNits / sdrReferenceWhiteNits;
912
+ return `color(display-p3 ${((color.r / index.rgbMax) * headroom).toString()} ${((color.g / index.rgbMax) * headroom).toString()} ${((color.b / index.rgbMax) * headroom).toString()} / ${(opacity ?? index.defaultOpacity).toString()})`;
1388
913
  }
1389
914
  function getSdrStyleFromRgb(color, opacity) {
1390
915
  return `rgba(${color.r.toString()}, ${color.g.toString()}, ${color.b.toString()}, ${(opacity ?? index.defaultOpacity).toString()})`;
1391
916
  }
1392
917
  function getStyleFromHsl(color, hdr, opacity) {
1393
918
  const op = opacity ?? index.defaultOpacity, key = `hsl-${color.h.toFixed(hslFixedPrecision)}-${color.s.toFixed(hslFixedPrecision)}-${color.l.toFixed(hslFixedPrecision)}-${hdr ? "hdr" : "sdr"}-${op.toString()}`;
1394
- return getCachedStyle(key, () => (hdr ? getHdrStyleFromHsl(color, opacity) : getSdrStyleFromHsl(color, opacity)));
1395
- }
1396
- function getHdrStyleFromHsl(color, opacity) {
1397
- return getHdrStyleFromRgb(hslToRgb(color), opacity);
1398
- }
1399
- function getSdrStyleFromHsl(color, opacity) {
1400
- return `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${(opacity ?? index.defaultOpacity).toString()})`;
919
+ return getCachedStyle(key, () => hdr
920
+ ? getStyleFromRgb(hslToRgb(color), true, opacity)
921
+ : `hsla(${color.h.toString()}, ${color.s.toString()}%, ${color.l.toString()}%, ${op.toString()})`);
1401
922
  }
1402
923
  function getHslFromAnimation(animation) {
1403
924
  return animation === undefined
@@ -1470,7 +991,7 @@ class RenderManager {
1470
991
  return;
1471
992
  }
1472
993
  this.draw(ctx => {
1473
- clear(ctx, this.#canvasManager.size);
994
+ ctx.clearRect(index.originPoint.x, index.originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
1474
995
  });
1475
996
  }
1476
997
  clear() {
@@ -1532,7 +1053,7 @@ class RenderManager {
1532
1053
  plugin.drawParticleSetup?.(context, particle, delta);
1533
1054
  }
1534
1055
  this.#applyPreDrawUpdaters(context, particle, radius, opacity, colorStyles, transform);
1535
- drawParticle({
1056
+ this.#drawParticle({
1536
1057
  container,
1537
1058
  context,
1538
1059
  particle,
@@ -1551,7 +1072,7 @@ class RenderManager {
1551
1072
  drawParticlePlugins(particle, delta) {
1552
1073
  this.draw(ctx => {
1553
1074
  for (const plugin of this.#drawParticlePlugins) {
1554
- drawParticlePlugin(ctx, plugin, particle, delta);
1075
+ this.#drawParticlePlugin(ctx, plugin, particle, delta);
1555
1076
  }
1556
1077
  });
1557
1078
  }
@@ -1651,12 +1172,19 @@ class RenderManager {
1651
1172
  }
1652
1173
  paintBase(baseColor) {
1653
1174
  this.draw(ctx => {
1654
- paintBase(ctx, this.#canvasManager.size, baseColor);
1175
+ ctx.fillStyle = baseColor ?? "rgba(0,0,0,0)";
1176
+ ctx.fillRect(index.originPoint.x, index.originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
1655
1177
  });
1656
1178
  }
1657
1179
  paintImage(image, opacity) {
1658
1180
  this.draw(ctx => {
1659
- paintImage(ctx, this.#canvasManager.size, image, opacity);
1181
+ if (!image) {
1182
+ return;
1183
+ }
1184
+ const prevAlpha = ctx.globalAlpha;
1185
+ ctx.globalAlpha = opacity;
1186
+ ctx.drawImage(image, index.originPoint.x, index.originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
1187
+ ctx.globalAlpha = prevAlpha;
1660
1188
  });
1661
1189
  }
1662
1190
  setContext(context) {
@@ -1670,15 +1198,15 @@ class RenderManager {
1670
1198
  }
1671
1199
  stop() {
1672
1200
  this.draw(ctx => {
1673
- clear(ctx, this.#canvasManager.size);
1201
+ ctx.clearRect(index.originPoint.x, index.originPoint.y, this.#canvasManager.size.width, this.#canvasManager.size.height);
1674
1202
  });
1675
1203
  }
1676
- #applyPostDrawUpdaters = particle => {
1204
+ #applyPostDrawUpdaters(particle) {
1677
1205
  for (const updater of this.#postDrawUpdaters) {
1678
1206
  updater.afterDraw?.(particle);
1679
1207
  }
1680
- };
1681
- #applyPreDrawUpdaters = (ctx, particle, radius, zOpacity, colorStyles, transform) => {
1208
+ }
1209
+ #applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform) {
1682
1210
  for (const updater of this.#preDrawUpdaters) {
1683
1211
  if (updater.getColorStyles) {
1684
1212
  const { fill, stroke } = updater.getColorStyles(particle, ctx, radius, zOpacity);
@@ -1697,8 +1225,114 @@ class RenderManager {
1697
1225
  }
1698
1226
  updater.beforeDraw?.(particle);
1699
1227
  }
1700
- };
1701
- #getPluginParticleColors = particle => {
1228
+ }
1229
+ #drawAfterEffect(drawer, data) {
1230
+ if (!drawer?.drawAfter) {
1231
+ return;
1232
+ }
1233
+ const { particle } = data;
1234
+ if (!particle.effect) {
1235
+ return;
1236
+ }
1237
+ drawer.drawAfter(data);
1238
+ }
1239
+ #drawBeforeEffect(drawer, data) {
1240
+ if (!drawer?.drawBefore) {
1241
+ return;
1242
+ }
1243
+ const { particle } = data;
1244
+ if (!particle.effect) {
1245
+ return;
1246
+ }
1247
+ drawer.drawBefore(data);
1248
+ }
1249
+ #drawParticle(data) {
1250
+ const { container, context, particle, delta, colorStyles, radius, opacity, transform } = data, { effectDrawers, shapeDrawers } = container, pos = particle.getPosition(), transformData = particle.getTransformData(transform), drawScale = index.defaultZoom, drawPosition = {
1251
+ x: pos.x,
1252
+ y: pos.y,
1253
+ };
1254
+ context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
1255
+ if (colorStyles.fill) {
1256
+ context.fillStyle = colorStyles.fill;
1257
+ }
1258
+ const fillEnabled = !!particle.fillEnabled, strokeWidth = particle.strokeWidth ?? index.minStrokeWidth;
1259
+ context.lineWidth = strokeWidth;
1260
+ if (colorStyles.stroke) {
1261
+ context.strokeStyle = colorStyles.stroke;
1262
+ }
1263
+ const drawData = {
1264
+ context,
1265
+ particle,
1266
+ radius,
1267
+ drawRadius: radius * drawScale,
1268
+ opacity,
1269
+ delta,
1270
+ pixelRatio: container.retina.pixelRatio,
1271
+ fill: fillEnabled,
1272
+ stroke: strokeWidth > index.minStrokeWidth,
1273
+ transformData,
1274
+ position: { ...pos },
1275
+ drawPosition,
1276
+ drawScale,
1277
+ };
1278
+ for (const plugin of container.plugins) {
1279
+ plugin.drawParticleTransform?.(drawData);
1280
+ }
1281
+ const effect = particle.effect ? effectDrawers.get(particle.effect) : undefined, shape = particle.shape ? shapeDrawers.get(particle.shape) : undefined;
1282
+ this.#drawBeforeEffect(effect, drawData);
1283
+ this.#drawShapeBeforeDraw(shape, drawData);
1284
+ this.#drawShape(shape, drawData);
1285
+ this.#drawShapeAfterDraw(shape, drawData);
1286
+ this.#drawAfterEffect(effect, drawData);
1287
+ context.resetTransform();
1288
+ }
1289
+ #drawParticlePlugin(context, plugin, particle, delta) {
1290
+ if (!plugin.drawParticle) {
1291
+ return;
1292
+ }
1293
+ plugin.drawParticle(context, particle, delta);
1294
+ }
1295
+ #drawShape(drawer, data) {
1296
+ if (!drawer) {
1297
+ return;
1298
+ }
1299
+ const { context, fill, particle, stroke } = data;
1300
+ if (!particle.shape) {
1301
+ return;
1302
+ }
1303
+ context.beginPath();
1304
+ drawer.draw(data);
1305
+ if (particle.shapeClose) {
1306
+ context.closePath();
1307
+ }
1308
+ if (fill) {
1309
+ context.fill();
1310
+ }
1311
+ if (stroke) {
1312
+ context.stroke();
1313
+ }
1314
+ }
1315
+ #drawShapeAfterDraw(drawer, data) {
1316
+ if (!drawer?.afterDraw) {
1317
+ return;
1318
+ }
1319
+ const { particle } = data;
1320
+ if (!particle.shape) {
1321
+ return;
1322
+ }
1323
+ drawer.afterDraw(data);
1324
+ }
1325
+ #drawShapeBeforeDraw(drawer, data) {
1326
+ if (!drawer?.beforeDraw) {
1327
+ return;
1328
+ }
1329
+ const { particle } = data;
1330
+ if (!particle.shape) {
1331
+ return;
1332
+ }
1333
+ drawer.beforeDraw(data);
1334
+ }
1335
+ #getPluginParticleColors(particle) {
1702
1336
  let fColor, sColor;
1703
1337
  for (const plugin of this.#colorPlugins) {
1704
1338
  if (!fColor && plugin.particleFillColor) {
@@ -1714,7 +1348,7 @@ class RenderManager {
1714
1348
  this.#reusablePluginColors[fColorIndex] = fColor;
1715
1349
  this.#reusablePluginColors[sColorIndex] = sColor;
1716
1350
  return this.#reusablePluginColors;
1717
- };
1351
+ }
1718
1352
  }
1719
1353
 
1720
1354
  const transferredCanvases = new WeakMap(), getTransferredCanvas = (canvas) => {
@@ -1846,6 +1480,7 @@ class CanvasManager {
1846
1480
  obs.observe(element, { attributes: true });
1847
1481
  });
1848
1482
  this.initPlugins();
1483
+ this.#initContext();
1849
1484
  this.render.init();
1850
1485
  }
1851
1486
  initBackground() {
@@ -1855,7 +1490,7 @@ class CanvasManager {
1855
1490
  }
1856
1491
  const elementStyle = element.style, color = rangeColorToRgb(this.#pluginManager, background.color);
1857
1492
  if (color) {
1858
- elementStyle.backgroundColor = getStyleFromRgb(color, container.hdr, background.opacity);
1493
+ elementStyle.backgroundColor = getStyleFromRgb(color, container.actualOptions.hdr, background.opacity);
1859
1494
  }
1860
1495
  else {
1861
1496
  elementStyle.backgroundColor = "";
@@ -1877,7 +1512,7 @@ class CanvasManager {
1877
1512
  if (this.#generated && this.domElement) {
1878
1513
  this.domElement.remove();
1879
1514
  }
1880
- const container = this.#container, domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
1515
+ const domCanvas = isHtmlCanvasElement(canvas) ? canvas : undefined;
1881
1516
  this.domElement = domCanvas;
1882
1517
  this.#generated = domCanvas ? domCanvas.dataset[index.generatedAttribute] === "true" : false;
1883
1518
  this.renderCanvas = domCanvas ? getTransferredCanvas(domCanvas) : canvas;
@@ -1898,26 +1533,6 @@ class CanvasManager {
1898
1533
  const pxRatio = this.#container.retina.pixelRatio, retinaSize = this.size;
1899
1534
  renderCanvas.height = retinaSize.height = standardSize.height * pxRatio;
1900
1535
  renderCanvas.width = retinaSize.width = standardSize.width * pxRatio;
1901
- const canSupportHdrQuery = index.safeMatchMedia("(color-gamut: p3)");
1902
- this.render.setContextSettings({
1903
- alpha: true,
1904
- colorSpace: canSupportHdrQuery?.matches && container.hdr ? "display-p3" : "srgb",
1905
- desynchronized: true,
1906
- willReadFrequently: false,
1907
- });
1908
- this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
1909
- this.#safeMutationObserver(obs => {
1910
- obs.disconnect();
1911
- });
1912
- container.retina.init();
1913
- this.initBackground();
1914
- this.#safeMutationObserver(obs => {
1915
- const element = this.domElement;
1916
- if (!element || !(element instanceof Node)) {
1917
- return;
1918
- }
1919
- obs.observe(element, { attributes: true });
1920
- });
1921
1536
  }
1922
1537
  resize() {
1923
1538
  const element = this.domElement;
@@ -1985,12 +1600,30 @@ class CanvasManager {
1985
1600
  await container.refresh();
1986
1601
  }
1987
1602
  }
1988
- #applyResizePlugins = () => {
1603
+ #applyResizePlugins() {
1989
1604
  for (const plugin of this.#resizePlugins) {
1990
1605
  plugin.resize?.();
1991
1606
  }
1992
- };
1993
- #initStyle = () => {
1607
+ }
1608
+ #initContext() {
1609
+ const container = this.#container, canSupportHdr = container.actualOptions.hdr &&
1610
+ index.safeMatchMedia("(color-gamut: p3)")?.matches &&
1611
+ index.safeMatchMedia("(dynamic-range: high)")?.matches;
1612
+ this.render.setContextSettings({
1613
+ alpha: true,
1614
+ desynchronized: true,
1615
+ willReadFrequently: false,
1616
+ ...(canSupportHdr
1617
+ ? { colorSpace: "display-p3", colorType: "float16" }
1618
+ : { colorSpace: "srgb" }),
1619
+ });
1620
+ const renderCanvas = this.renderCanvas;
1621
+ if (!renderCanvas) {
1622
+ return;
1623
+ }
1624
+ this.render.setContext(renderCanvas.getContext("2d", this.render.settings));
1625
+ }
1626
+ #initStyle() {
1994
1627
  const element = this.domElement, options = this.#container.actualOptions;
1995
1628
  if (!element) {
1996
1629
  return;
@@ -2011,8 +1644,8 @@ class CanvasManager {
2011
1644
  }
2012
1645
  element.style.setProperty(key, value, "important");
2013
1646
  }
2014
- };
2015
- #repairStyle = () => {
1647
+ }
1648
+ #repairStyle() {
2016
1649
  const element = this.domElement;
2017
1650
  if (!element) {
2018
1651
  return;
@@ -2031,27 +1664,27 @@ class CanvasManager {
2031
1664
  }
2032
1665
  observer.observe(element, { attributes: true });
2033
1666
  });
2034
- };
2035
- #resetOriginalStyle = () => {
1667
+ }
1668
+ #resetOriginalStyle() {
2036
1669
  const element = this.domElement, originalStyle = this.#originalStyle;
2037
1670
  if (!element || !originalStyle) {
2038
1671
  return;
2039
1672
  }
2040
1673
  setStyle(element, originalStyle, true);
2041
- };
2042
- #safeMutationObserver = callback => {
1674
+ }
1675
+ #safeMutationObserver(callback) {
2043
1676
  if (!this.#mutationObserver) {
2044
1677
  return;
2045
1678
  }
2046
1679
  callback(this.#mutationObserver);
2047
- };
2048
- #setFullScreenStyle = () => {
1680
+ }
1681
+ #setFullScreenStyle() {
2049
1682
  const element = this.domElement;
2050
1683
  if (!element) {
2051
1684
  return;
2052
1685
  }
2053
1686
  setStyle(element, index.getFullScreenStyle(this.#container.actualOptions.fullScreen.zIndex), true);
2054
- };
1687
+ }
2055
1688
  }
2056
1689
 
2057
1690
  class EventListeners {
@@ -2076,7 +1709,7 @@ class EventListeners {
2076
1709
  removeListeners() {
2077
1710
  this.#manageListeners(false);
2078
1711
  }
2079
- #handleVisibilityChange = () => {
1712
+ #handleVisibilityChange() {
2080
1713
  const container = this.#container, options = container.actualOptions;
2081
1714
  if (!options.pauseOnBlur) {
2082
1715
  return;
@@ -2094,8 +1727,8 @@ class EventListeners {
2094
1727
  container.draw(true);
2095
1728
  }
2096
1729
  }
2097
- };
2098
- #handleWindowResize = () => {
1730
+ }
1731
+ #handleWindowResize() {
2099
1732
  if (this.#resizeTimeout) {
2100
1733
  clearTimeout(this.#resizeTimeout);
2101
1734
  this.#resizeTimeout = undefined;
@@ -2105,13 +1738,13 @@ class EventListeners {
2105
1738
  await canvas.windowResize();
2106
1739
  };
2107
1740
  this.#resizeTimeout = setTimeout(() => void handleResize(), this.#container.actualOptions.resize.delay * index.millisecondsToSeconds);
2108
- };
2109
- #manageListeners = add => {
1741
+ }
1742
+ #manageListeners(add) {
2110
1743
  const handlers = this.#handlers;
2111
1744
  this.#manageResize(add);
2112
1745
  index.manageListener(document, index.visibilityChangeEvent, handlers.visibilityChange, add, false);
2113
- };
2114
- #manageResize = add => {
1746
+ }
1747
+ #manageResize(add) {
2115
1748
  const handlers = this.#handlers, container = this.#container, options = container.actualOptions;
2116
1749
  if (!options.resize.enable) {
2117
1750
  return;
@@ -2138,7 +1771,7 @@ class EventListeners {
2138
1771
  });
2139
1772
  this.#resizeObserver.observe(canvasEl);
2140
1773
  }
2141
- };
1774
+ }
2142
1775
  }
2143
1776
 
2144
1777
  function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
@@ -2165,6 +1798,131 @@ function fixOutMode(data) {
2165
1798
  data.setCb(data.radius);
2166
1799
  }
2167
1800
  }
1801
+ function normalizeAngle(angle, modulus) {
1802
+ const normalized = angle % modulus;
1803
+ return normalized < index.defaultAngle ? normalized + modulus : normalized;
1804
+ }
1805
+ function initParticleState(particle, id, group) {
1806
+ particle.id = id;
1807
+ particle.group = group;
1808
+ particle.justWarped = false;
1809
+ particle.effectClose = true;
1810
+ particle.shapeClose = true;
1811
+ particle.pathRotation = false;
1812
+ particle.lastPathTime = 0;
1813
+ particle.destroyed = false;
1814
+ particle.unbreakable = false;
1815
+ particle.isRotating = false;
1816
+ particle.rotation = 0;
1817
+ particle.misplaced = false;
1818
+ particle.retina = {
1819
+ maxDistance: {},
1820
+ maxSpeed: 0,
1821
+ moveDrift: 0,
1822
+ moveSpeed: 0,
1823
+ sizeAnimationSpeed: 0,
1824
+ };
1825
+ particle.size = {
1826
+ value: 1,
1827
+ max: 1,
1828
+ min: 1,
1829
+ enable: false,
1830
+ };
1831
+ particle.outType = index.ParticleOutType.normal;
1832
+ particle.ignoresResizeRatio = true;
1833
+ }
1834
+ function resolveParticleOptions(particle, container, pluginManager, overrideOptions) {
1835
+ const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates;
1836
+ particle.effect = index.itemFromSingleOrMultiple(particlesOptions.effect.type, particle.id, reduceDuplicates);
1837
+ particle.shape = index.itemFromSingleOrMultiple(particlesOptions.shape.type, particle.id, reduceDuplicates);
1838
+ const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
1839
+ if (overrideOptions) {
1840
+ if (overrideOptions.effect) {
1841
+ const overrideEffectType = overrideOptions.effect.type;
1842
+ if (overrideEffectType && overrideEffectType !== particle.effect) {
1843
+ const effect = index.itemFromSingleOrMultiple(overrideEffectType, particle.id, reduceDuplicates);
1844
+ if (effect) {
1845
+ particle.effect = effect;
1846
+ }
1847
+ }
1848
+ effectOptions.load(overrideOptions.effect);
1849
+ }
1850
+ if (overrideOptions.shape) {
1851
+ const overrideShapeType = overrideOptions.shape.type;
1852
+ if (overrideShapeType && overrideShapeType !== particle.shape) {
1853
+ const shape = index.itemFromSingleOrMultiple(overrideShapeType, particle.id, reduceDuplicates);
1854
+ if (shape) {
1855
+ particle.shape = shape;
1856
+ }
1857
+ }
1858
+ shapeOptions.load(overrideOptions.shape);
1859
+ }
1860
+ }
1861
+ if (particle.effect === index.randomColorValue) {
1862
+ const availableEffects = [...container.effectDrawers.keys()];
1863
+ particle.effect = availableEffects[Math.floor(index.getRandom() * availableEffects.length)];
1864
+ }
1865
+ if (particle.shape === index.randomColorValue) {
1866
+ const availableShapes = [...container.shapeDrawers.keys()];
1867
+ particle.shape = availableShapes[Math.floor(index.getRandom() * availableShapes.length)];
1868
+ }
1869
+ particle.effectData = particle.effect
1870
+ ? loadEffectData(particle.effect, effectOptions, particle.id, reduceDuplicates)
1871
+ : undefined;
1872
+ particle.shapeData = particle.shape
1873
+ ? loadShapeData(particle.shape, shapeOptions, particle.id, reduceDuplicates)
1874
+ : undefined;
1875
+ particlesOptions.load(overrideOptions);
1876
+ const effectData = particle.effectData, shapeData = particle.shapeData;
1877
+ if (effectData) {
1878
+ particlesOptions.load(effectData.particles);
1879
+ }
1880
+ if (shapeData) {
1881
+ particlesOptions.load(shapeData.particles);
1882
+ }
1883
+ particle.effectClose = effectData?.close ?? particlesOptions.effect.close;
1884
+ particle.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
1885
+ return particlesOptions;
1886
+ }
1887
+ function initParticleDrawers(particle, container) {
1888
+ let effectDrawer, shapeDrawer;
1889
+ if (particle.effect) {
1890
+ effectDrawer = container.effectDrawers.get(particle.effect);
1891
+ }
1892
+ if (effectDrawer?.loadEffect) {
1893
+ effectDrawer.loadEffect(particle);
1894
+ }
1895
+ if (particle.shape) {
1896
+ shapeDrawer = container.shapeDrawers.get(particle.shape);
1897
+ }
1898
+ if (shapeDrawer?.loadShape) {
1899
+ shapeDrawer.loadShape(particle);
1900
+ }
1901
+ const sideCountFunc = shapeDrawer?.getSidesCount;
1902
+ if (sideCountFunc) {
1903
+ particle.sides = sideCountFunc(particle);
1904
+ }
1905
+ }
1906
+ function runUpdaterPreInit(updaters, particle) {
1907
+ for (const updater of updaters) {
1908
+ updater.preInit?.(particle);
1909
+ }
1910
+ }
1911
+ function runUpdaterInit(updaters, particle) {
1912
+ for (const updater of updaters) {
1913
+ updater.init(particle);
1914
+ }
1915
+ }
1916
+ function runDrawerInit(container, particle) {
1917
+ const shapeDrawer = particle.shape ? container.shapeDrawers.get(particle.shape) : undefined, effectDrawer = particle.effect ? container.effectDrawers.get(particle.effect) : undefined;
1918
+ effectDrawer?.particleInit?.(container, particle);
1919
+ shapeDrawer?.particleInit?.(container, particle);
1920
+ }
1921
+ function runParticleCreatedPlugins(container, particle) {
1922
+ for (const plugin of container.particleCreatedPlugins) {
1923
+ plugin.particleCreated?.(particle);
1924
+ }
1925
+ }
2168
1926
  class Particle {
2169
1927
  backColor;
2170
1928
  bubble;
@@ -2300,78 +2058,10 @@ class Particle {
2300
2058
  }
2301
2059
  init(id, position, overrideOptions, group) {
2302
2060
  const container = this.#container;
2303
- this.id = id;
2304
- this.group = group;
2305
- this.justWarped = false;
2306
- this.effectClose = true;
2307
- this.shapeClose = true;
2308
- this.pathRotation = false;
2309
- this.lastPathTime = 0;
2310
- this.destroyed = false;
2311
- this.unbreakable = false;
2312
- this.isRotating = false;
2313
- this.rotation = 0;
2314
- this.misplaced = false;
2315
- this.retina = {
2316
- maxDistance: {},
2317
- maxSpeed: 0,
2318
- moveDrift: 0,
2319
- moveSpeed: 0,
2320
- sizeAnimationSpeed: 0,
2321
- };
2322
- this.size = {
2323
- value: 1,
2324
- max: 1,
2325
- min: 1,
2326
- enable: false,
2327
- };
2328
- this.outType = index.ParticleOutType.normal;
2329
- this.ignoresResizeRatio = true;
2330
- const mainOptions = container.actualOptions, particlesOptions = loadParticlesOptions(this.#pluginManager, container, mainOptions.particles), reduceDuplicates = particlesOptions.reduceDuplicates, effectType = particlesOptions.effect.type, shapeType = particlesOptions.shape.type;
2331
- this.effect = index.itemFromSingleOrMultiple(effectType, this.id, reduceDuplicates);
2332
- this.shape = index.itemFromSingleOrMultiple(shapeType, this.id, reduceDuplicates);
2333
- const effectOptions = particlesOptions.effect, shapeOptions = particlesOptions.shape;
2334
- if (overrideOptions) {
2335
- if (overrideOptions.effect?.type && overrideOptions.effect.type !== this.effect) {
2336
- const overrideEffectType = overrideOptions.effect.type, effect = index.itemFromSingleOrMultiple(overrideEffectType, this.id, reduceDuplicates);
2337
- if (effect) {
2338
- this.effect = effect;
2339
- effectOptions.load(overrideOptions.effect);
2340
- }
2341
- }
2342
- if (overrideOptions.shape?.type && overrideOptions.shape.type !== this.shape) {
2343
- const overrideShapeType = overrideOptions.shape.type, shape = index.itemFromSingleOrMultiple(overrideShapeType, this.id, reduceDuplicates);
2344
- if (shape) {
2345
- this.shape = shape;
2346
- shapeOptions.load(overrideOptions.shape);
2347
- }
2348
- }
2349
- }
2350
- if (this.effect === index.randomColorValue) {
2351
- const availableEffects = [...this.#container.effectDrawers.keys()];
2352
- this.effect = availableEffects[Math.floor(index.getRandom() * availableEffects.length)];
2353
- }
2354
- if (this.shape === index.randomColorValue) {
2355
- const availableShapes = [...this.#container.shapeDrawers.keys()];
2356
- this.shape = availableShapes[Math.floor(index.getRandom() * availableShapes.length)];
2357
- }
2358
- this.effectData = this.effect ? loadEffectData(this.effect, effectOptions, this.id, reduceDuplicates) : undefined;
2359
- this.shapeData = this.shape ? loadShapeData(this.shape, shapeOptions, this.id, reduceDuplicates) : undefined;
2360
- particlesOptions.load(overrideOptions);
2361
- const effectData = this.effectData, shapeData = this.shapeData;
2362
- if (effectData) {
2363
- particlesOptions.load(effectData.particles);
2364
- }
2365
- if (shapeData) {
2366
- particlesOptions.load(shapeData.particles);
2367
- }
2368
- this.effectClose = effectData?.close ?? particlesOptions.effect.close;
2369
- this.shapeClose = shapeData?.close ?? particlesOptions.shape.close;
2370
- this.options = particlesOptions;
2061
+ initParticleState(this, id, group);
2062
+ this.options = resolveParticleOptions(this, container, this.#pluginManager, overrideOptions);
2371
2063
  container.retina.initParticle(this);
2372
- for (const updater of container.particleUpdaters) {
2373
- updater.preInit?.(this);
2374
- }
2064
+ runUpdaterPreInit(container.particleUpdaters, this);
2375
2065
  this.bubble = {
2376
2066
  inRange: false,
2377
2067
  };
@@ -2384,32 +2074,11 @@ class Particle {
2384
2074
  this.velocity = this.initialVelocity.copy();
2385
2075
  this.zIndexFactor = this.position.z / container.zLayers;
2386
2076
  this.sides = 24;
2387
- let effectDrawer, shapeDrawer;
2388
- if (this.effect) {
2389
- effectDrawer = container.effectDrawers.get(this.effect);
2390
- }
2391
- if (effectDrawer?.loadEffect) {
2392
- effectDrawer.loadEffect(this);
2393
- }
2394
- if (this.shape) {
2395
- shapeDrawer = container.shapeDrawers.get(this.shape);
2396
- }
2397
- if (shapeDrawer?.loadShape) {
2398
- shapeDrawer.loadShape(this);
2399
- }
2400
- const sideCountFunc = shapeDrawer?.getSidesCount;
2401
- if (sideCountFunc) {
2402
- this.sides = sideCountFunc(this);
2403
- }
2077
+ initParticleDrawers(this, container);
2404
2078
  this.spawning = false;
2405
- for (const updater of container.particleUpdaters) {
2406
- updater.init(this);
2407
- }
2408
- effectDrawer?.particleInit?.(container, this);
2409
- shapeDrawer?.particleInit?.(container, this);
2410
- for (const plugin of container.particleCreatedPlugins) {
2411
- plugin.particleCreated?.(this);
2412
- }
2079
+ runUpdaterInit(container.particleUpdaters, this);
2080
+ runDrawerInit(container, this);
2081
+ runParticleCreatedPlugins(container, this);
2413
2082
  }
2414
2083
  isInsideCanvas(direction) {
2415
2084
  return this.#getInsideCanvasResult({ direction }).inside;
@@ -2423,15 +2092,15 @@ class Particle {
2423
2092
  }
2424
2093
  const angle = this.roll.angle;
2425
2094
  if (this.roll.horizontal && this.roll.vertical) {
2426
- const normalizedAngle = angle % index.doublePI, adjustedAngle = normalizedAngle < index.defaultAngle ? normalizedAngle + index.doublePI : normalizedAngle;
2095
+ const adjustedAngle = normalizeAngle(angle, index.doublePI);
2427
2096
  return adjustedAngle >= Math.PI * index.half && adjustedAngle < Math.PI * index.triple * index.half;
2428
2097
  }
2429
2098
  if (this.roll.horizontal) {
2430
- const normalizedAngle = (angle + Math.PI * index.half) % (Math.PI * index.double), adjustedAngle = normalizedAngle < index.defaultAngle ? normalizedAngle + Math.PI * index.double : normalizedAngle;
2099
+ const adjustedAngle = normalizeAngle(angle + Math.PI * index.half, index.doublePI);
2431
2100
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * index.double;
2432
2101
  }
2433
2102
  if (this.roll.vertical) {
2434
- const normalizedAngle = angle % (Math.PI * index.double), adjustedAngle = normalizedAngle < index.defaultAngle ? normalizedAngle + Math.PI * index.double : normalizedAngle;
2103
+ const adjustedAngle = normalizeAngle(angle, index.doublePI);
2435
2104
  return adjustedAngle >= Math.PI && adjustedAngle < Math.PI * index.double;
2436
2105
  }
2437
2106
  return false;
@@ -2444,10 +2113,10 @@ class Particle {
2444
2113
  updater.reset?.(this);
2445
2114
  }
2446
2115
  }
2447
- #calcPosition = (position, zIndex) => {
2116
+ #calcPosition(position, zIndex) {
2448
2117
  let tryCount = index.defaultRetryCount, posVec = position ? index.Vector3d.create(position.x, position.y, zIndex) : undefined;
2449
- const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size, abortController = new AbortController(), { signal } = abortController;
2450
- while (!signal.aborted) {
2118
+ const container = this.#container, plugins = container.particlePositionPlugins, outModes = this.options.move.outModes, radius = this.getRadius(), canvasSize = container.canvas.size;
2119
+ for (;;) {
2451
2120
  for (const plugin of plugins) {
2452
2121
  const pluginPos = plugin.particlePosition?.(posVec, this);
2453
2122
  if (pluginPos) {
@@ -2475,9 +2144,8 @@ class Particle {
2475
2144
  tryCount += index.tryCountIncrement;
2476
2145
  posVec = undefined;
2477
2146
  }
2478
- return posVec;
2479
- };
2480
- #calculateVelocity = () => {
2147
+ }
2148
+ #calculateVelocity() {
2481
2149
  const moveOptions = this.options.move, baseVelocity = index.getParticleBaseVelocity(this.direction), res = baseVelocity.copy();
2482
2150
  if (moveOptions.direction === index.MoveDirection.inside || moveOptions.direction === index.MoveDirection.outside) {
2483
2151
  return res;
@@ -2493,8 +2161,8 @@ class Particle {
2493
2161
  res.length *= index.getRandom();
2494
2162
  }
2495
2163
  return res;
2496
- };
2497
- #fixHorizontal = (pos, radius, outMode) => {
2164
+ }
2165
+ #fixHorizontal(pos, radius, outMode) {
2498
2166
  fixOutMode({
2499
2167
  outMode,
2500
2168
  checkModes: [index.OutMode.bounce],
@@ -2503,8 +2171,8 @@ class Particle {
2503
2171
  setCb: (value) => (pos.x += value),
2504
2172
  radius,
2505
2173
  });
2506
- };
2507
- #fixVertical = (pos, radius, outMode) => {
2174
+ }
2175
+ #fixVertical(pos, radius, outMode) {
2508
2176
  fixOutMode({
2509
2177
  outMode,
2510
2178
  checkModes: [index.OutMode.bounce],
@@ -2513,8 +2181,8 @@ class Particle {
2513
2181
  setCb: (value) => (pos.y += value),
2514
2182
  radius,
2515
2183
  });
2516
- };
2517
- #getDefaultInsideCanvasResult = (direction, outMode) => {
2184
+ }
2185
+ #getDefaultInsideCanvasResult(direction, outMode) {
2518
2186
  const radius = this.getRadius(), canvasSize = this.#container.canvas.size, position = this.position, isBounce = outMode === index.OutMode.bounce;
2519
2187
  if (direction === index.OutModeDirection.bottom) {
2520
2188
  return {
@@ -2547,8 +2215,8 @@ class Particle {
2547
2215
  position.x <= canvasSize.width + radius,
2548
2216
  reason: "default",
2549
2217
  };
2550
- };
2551
- #getInsideCanvasCallbackData = (direction, outMode) => {
2218
+ }
2219
+ #getInsideCanvasCallbackData(direction, outMode) {
2552
2220
  return {
2553
2221
  canvasSize: this.#container.canvas.size,
2554
2222
  direction,
@@ -2556,8 +2224,8 @@ class Particle {
2556
2224
  particle: this,
2557
2225
  radius: this.getRadius(),
2558
2226
  };
2559
- };
2560
- #getInsideCanvasResult = (data) => {
2227
+ }
2228
+ #getInsideCanvasResult(data) {
2561
2229
  const defaultResult = this.#getDefaultInsideCanvasResult(data.direction, data.outMode), container = this.#container, shapeDrawer = this.shape ? container.shapeDrawers.get(this.shape) : undefined, effectDrawer = this.effect ? container.effectDrawers.get(this.effect) : undefined, shapeCheck = shapeDrawer?.isInsideCanvas, effectCheck = effectDrawer?.isInsideCanvas;
2562
2230
  if (!shapeCheck && !effectCheck) {
2563
2231
  return defaultResult;
@@ -2572,8 +2240,8 @@ class Particle {
2572
2240
  };
2573
2241
  }
2574
2242
  return shapeResult ?? effectResult ?? defaultResult;
2575
- };
2576
- #getRollColor = color => {
2243
+ }
2244
+ #getRollColor(color) {
2577
2245
  if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
2578
2246
  return color;
2579
2247
  }
@@ -2587,8 +2255,8 @@ class Particle {
2587
2255
  return alterHsl(color, this.roll.alter.type, this.roll.alter.value);
2588
2256
  }
2589
2257
  return color;
2590
- };
2591
- #initPosition = position => {
2258
+ }
2259
+ #initPosition(position) {
2592
2260
  const container = this.#container, zIndexValue = Math.floor(index.getRangeValue(this.options.zIndex.value)), initialPosition = this.#calcPosition(position, index.clamp(zIndexValue, index.minZ, container.zLayers));
2593
2261
  if (!initialPosition) {
2594
2262
  throw new Error("a valid position cannot be found for particle");
@@ -2611,8 +2279,8 @@ class Particle {
2611
2279
  break;
2612
2280
  }
2613
2281
  this.offset = index.Vector.origin;
2614
- };
2615
- #normalizeInsideCanvasResult = (result, reason) => {
2282
+ }
2283
+ #normalizeInsideCanvasResult(result, reason) {
2616
2284
  if (typeof result === "boolean") {
2617
2285
  return {
2618
2286
  inside: result,
@@ -2624,7 +2292,7 @@ class Particle {
2624
2292
  margin: result.margin,
2625
2293
  reason: result.reason ?? reason,
2626
2294
  };
2627
- };
2295
+ }
2628
2296
  }
2629
2297
 
2630
2298
  class SpatialHashGrid {
@@ -2977,10 +2645,10 @@ class ParticlesManager {
2977
2645
  }
2978
2646
  this.#resizeFactor = undefined;
2979
2647
  }
2980
- #addToPool = (...particles) => {
2648
+ #addToPool(...particles) {
2981
2649
  this.#pool.push(...particles);
2982
- };
2983
- #applyDensity = (options, pluginsCount, group, groupOptions) => {
2650
+ }
2651
+ #applyDensity(options, pluginsCount, group, groupOptions) {
2984
2652
  const numberOptions = options.number;
2985
2653
  if (!numberOptions.density.enable) {
2986
2654
  if (group === undefined) {
@@ -3004,36 +2672,19 @@ class ParticlesManager {
3004
2672
  else if (particlesCount > particlesNumber) {
3005
2673
  this.removeQuantity(particlesCount - particlesNumber, group);
3006
2674
  }
3007
- };
3008
- #createBuckets = (zLayers) => {
2675
+ }
2676
+ #createBuckets(zLayers) {
3009
2677
  const bucketCount = Math.max(Math.floor(zLayers), index.one);
3010
2678
  return Array.from({ length: bucketCount }, () => []);
3011
- };
3012
- #getBucketIndex = (zIndex) => {
2679
+ }
2680
+ #getBucketIndex(zIndex) {
3013
2681
  const maxBucketIndex = this.#zBuckets.length - index.one;
3014
2682
  if (maxBucketIndex <= index.minIndex) {
3015
2683
  return index.minIndex;
3016
2684
  }
3017
2685
  return Math.min(Math.max(Math.floor(zIndex), index.minIndex), maxBucketIndex);
3018
- };
3019
- #getParticleInsertIndex = (bucket, particleId) => {
3020
- let start = index.minIndex, end = bucket.length;
3021
- while (start < end) {
3022
- const middle = Math.floor((start + end) / index.double), middleParticle = bucket[middle];
3023
- if (!middleParticle) {
3024
- end = middle;
3025
- continue;
3026
- }
3027
- if (middleParticle.id < particleId) {
3028
- start = middle + index.one;
3029
- }
3030
- else {
3031
- end = middle;
3032
- }
3033
- }
3034
- return start;
3035
- };
3036
- #initDensityFactor = densityOptions => {
2686
+ }
2687
+ #initDensityFactor(densityOptions) {
3037
2688
  const container = this.#container;
3038
2689
  if (!densityOptions.enable) {
3039
2690
  return index.defaultDensityFactor;
@@ -3043,16 +2694,16 @@ class ParticlesManager {
3043
2694
  return index.defaultDensityFactor;
3044
2695
  }
3045
2696
  return ((canvasSize.width * canvasSize.height) / (densityOptions.height * densityOptions.width * pxRatio ** index.squareExp));
3046
- };
3047
- #insertParticleIntoBucket = (particle) => {
2697
+ }
2698
+ #insertParticleIntoBucket(particle) {
3048
2699
  const bucketIndex = this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
3049
2700
  if (!bucket) {
3050
2701
  return;
3051
2702
  }
3052
- bucket.splice(this.#getParticleInsertIndex(bucket, particle.id), index.empty, particle);
2703
+ bucket.push(particle);
3053
2704
  this.#particleBuckets.set(particle.id, bucketIndex);
3054
- };
3055
- #removeParticle = (index$1, group, override) => {
2705
+ }
2706
+ #removeParticle(index$1, group, override) {
3056
2707
  const particle = this.#array[index$1];
3057
2708
  if (!particle) {
3058
2709
  return false;
@@ -3068,22 +2719,20 @@ class ParticlesManager {
3068
2719
  });
3069
2720
  this.#addToPool(particle);
3070
2721
  return true;
3071
- };
3072
- #removeParticleFromBucket = (particle) => {
2722
+ }
2723
+ #removeParticleFromBucket(particle) {
3073
2724
  const bucketIndex = this.#particleBuckets.get(particle.id) ?? this.#getBucketIndex(particle.position.z), bucket = this.#zBuckets[bucketIndex];
3074
2725
  if (!bucket) {
3075
2726
  this.#particleBuckets.delete(particle.id);
3076
2727
  return;
3077
2728
  }
3078
- const particleIndex = this.#getParticleInsertIndex(bucket, particle.id);
3079
- if (bucket[particleIndex]?.id !== particle.id) {
3080
- this.#particleBuckets.delete(particle.id);
3081
- return;
2729
+ const idx = bucket.findIndex(p => p.id === particle.id);
2730
+ if (idx >= index.minIndex) {
2731
+ bucket.splice(idx, index.deleteCount);
3082
2732
  }
3083
- bucket.splice(particleIndex, index.deleteCount);
3084
2733
  this.#particleBuckets.delete(particle.id);
3085
- };
3086
- #resetBuckets = (zLayers) => {
2734
+ }
2735
+ #resetBuckets(zLayers) {
3087
2736
  const bucketCount = Math.max(Math.floor(zLayers), index.one);
3088
2737
  if (this.#zBuckets.length !== bucketCount) {
3089
2738
  this.#zBuckets = this.#createBuckets(bucketCount);
@@ -3092,8 +2741,8 @@ class ParticlesManager {
3092
2741
  for (const bucket of this.#zBuckets) {
3093
2742
  bucket.length = index.minIndex;
3094
2743
  }
3095
- };
3096
- #updateParticleBucket = (particle) => {
2744
+ }
2745
+ #updateParticleBucket(particle) {
3097
2746
  const newBucketIndex = this.#getBucketIndex(particle.position.z), currentBucketIndex = this.#particleBuckets.get(particle.id);
3098
2747
  if (currentBucketIndex === undefined) {
3099
2748
  this.#insertParticleIntoBucket(particle);
@@ -3104,9 +2753,9 @@ class ParticlesManager {
3104
2753
  }
3105
2754
  const currentBucket = this.#zBuckets[currentBucketIndex];
3106
2755
  if (currentBucket) {
3107
- const particleIndex = this.#getParticleInsertIndex(currentBucket, particle.id);
3108
- if (currentBucket[particleIndex]?.id === particle.id) {
3109
- currentBucket.splice(particleIndex, index.deleteCount);
2756
+ const idx = currentBucket.findIndex(p => p.id === particle.id);
2757
+ if (idx >= index.minIndex) {
2758
+ currentBucket.splice(idx, index.deleteCount);
3110
2759
  }
3111
2760
  }
3112
2761
  const newBucket = this.#zBuckets[newBucketIndex];
@@ -3114,10 +2763,16 @@ class ParticlesManager {
3114
2763
  this.#particleBuckets.set(particle.id, newBucketIndex);
3115
2764
  return;
3116
2765
  }
3117
- newBucket.splice(this.#getParticleInsertIndex(newBucket, particle.id), index.empty, particle);
2766
+ newBucket.push(particle);
2767
+ if (newBucket.length >= index.double) {
2768
+ const prev = newBucket[newBucket.length - index.double];
2769
+ if (prev && particle.id < prev.id) {
2770
+ newBucket.sort((a, b) => a.id - b.id);
2771
+ }
2772
+ }
3118
2773
  this.#particleBuckets.set(particle.id, newBucketIndex);
3119
- };
3120
- #updateParticlesPhase1 = (delta) => {
2774
+ }
2775
+ #updateParticlesPhase1(delta) {
3121
2776
  const particlesToDelete = new Set(), resizeFactor = this.#resizeFactor;
3122
2777
  for (const particle of this.#array) {
3123
2778
  if (resizeFactor && !particle.ignoresResizeRatio) {
@@ -3143,8 +2798,8 @@ class ParticlesManager {
3143
2798
  this.grid.insert(particle);
3144
2799
  }
3145
2800
  return particlesToDelete;
3146
- };
3147
- #updateParticlesPhase2 = (delta, particlesToDelete) => {
2801
+ }
2802
+ #updateParticlesPhase2(delta, particlesToDelete) {
3148
2803
  for (const particle of this.#array) {
3149
2804
  if (particle.destroyed) {
3150
2805
  particlesToDelete.add(particle);
@@ -3160,7 +2815,7 @@ class ParticlesManager {
3160
2815
  }
3161
2816
  this.#updateParticleBucket(particle);
3162
2817
  }
3163
- };
2818
+ }
3164
2819
  }
3165
2820
 
3166
2821
  class Retina {
@@ -3522,7 +3177,7 @@ class Container {
3522
3177
  }
3523
3178
  return refresh;
3524
3179
  }
3525
- #nextFrame = (timestamp) => {
3180
+ #nextFrame(timestamp) {
3526
3181
  try {
3527
3182
  if (!this.#smooth &&
3528
3183
  this.#lastFrameTime !== undefined &&
@@ -3550,7 +3205,7 @@ class Container {
3550
3205
  catch (e) {
3551
3206
  index.getLogger().error("error in animation loop", e);
3552
3207
  }
3553
- };
3208
+ }
3554
3209
  }
3555
3210
 
3556
3211
  exports.Container = Container;