@tsparticles/engine 3.1.0 → 3.2.1

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 (73) hide show
  1. package/373.min.js +2 -0
  2. package/373.min.js.LICENSE.txt +1 -0
  3. package/438.min.js +2 -0
  4. package/438.min.js.LICENSE.txt +1 -0
  5. package/README.md +72 -71
  6. package/browser/Core/Canvas.js +85 -32
  7. package/browser/Core/Container.js +8 -7
  8. package/browser/Core/Engine.js +14 -15
  9. package/browser/Core/Particle.js +14 -15
  10. package/browser/Core/Particles.js +42 -35
  11. package/browser/Core/Utils/EventListeners.js +1 -1
  12. package/browser/Core/Utils/InteractionManager.js +3 -2
  13. package/browser/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  14. package/browser/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  15. package/browser/Utils/CanvasUtils.js +14 -14
  16. package/cjs/Core/Canvas.js +85 -32
  17. package/cjs/Core/Container.js +8 -7
  18. package/cjs/Core/Engine.js +37 -15
  19. package/cjs/Core/Particle.js +14 -15
  20. package/cjs/Core/Particles.js +65 -35
  21. package/cjs/Core/Utils/EventListeners.js +1 -1
  22. package/cjs/Core/Utils/InteractionManager.js +3 -2
  23. package/cjs/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  24. package/cjs/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  25. package/cjs/Utils/CanvasUtils.js +14 -14
  26. package/dist_browser_Core_Container_js.js +92 -0
  27. package/dist_browser_Core_Particle_js.js +32 -0
  28. package/esm/Core/Canvas.js +85 -32
  29. package/esm/Core/Container.js +8 -7
  30. package/esm/Core/Engine.js +14 -15
  31. package/esm/Core/Particle.js +14 -15
  32. package/esm/Core/Particles.js +42 -35
  33. package/esm/Core/Utils/EventListeners.js +1 -1
  34. package/esm/Core/Utils/InteractionManager.js +3 -2
  35. package/esm/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  36. package/esm/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  37. package/esm/Utils/CanvasUtils.js +14 -14
  38. package/package.json +1 -1
  39. package/report.html +3 -3
  40. package/tsparticles.engine.js +894 -5820
  41. package/tsparticles.engine.min.js +1 -1
  42. package/tsparticles.engine.min.js.LICENSE.txt +1 -1
  43. package/types/Core/Canvas.d.ts +5 -3
  44. package/types/Core/Container.d.ts +1 -1
  45. package/types/Core/Engine.d.ts +13 -8
  46. package/types/Core/Interfaces/IContainerPlugin.d.ts +3 -3
  47. package/types/Core/Interfaces/IEffectDrawer.d.ts +3 -3
  48. package/types/Core/Interfaces/IMovePathGenerator.d.ts +2 -2
  49. package/types/Core/Interfaces/IParticleMover.d.ts +2 -2
  50. package/types/Core/Interfaces/IParticleUpdater.d.ts +2 -2
  51. package/types/Core/Interfaces/IPlugin.d.ts +1 -1
  52. package/types/Core/Interfaces/IShapeDrawer.d.ts +4 -4
  53. package/types/Core/Particle.d.ts +3 -3
  54. package/types/Core/Particles.d.ts +12 -8
  55. package/types/Core/Utils/InteractionManager.d.ts +2 -2
  56. package/types/Enums/Modes/OutMode.d.ts +0 -3
  57. package/types/Options/Classes/BackgroundMask/BackgroundMaskCover.d.ts +2 -1
  58. package/types/Options/Classes/Particles/Move/OutModes.d.ts +6 -6
  59. package/types/Options/Interfaces/BackgroundMask/IBackgroundMask.d.ts +2 -1
  60. package/types/Options/Interfaces/BackgroundMask/IBackgroundMaskCover.d.ts +2 -1
  61. package/types/Options/Interfaces/Particles/Move/IMove.d.ts +2 -2
  62. package/types/Options/Interfaces/Particles/Move/IOutModes.d.ts +6 -6
  63. package/types/Utils/CanvasUtils.d.ts +6 -6
  64. package/umd/Core/Canvas.js +85 -32
  65. package/umd/Core/Container.js +8 -7
  66. package/umd/Core/Engine.js +39 -16
  67. package/umd/Core/Particle.js +14 -15
  68. package/umd/Core/Particles.js +67 -36
  69. package/umd/Core/Utils/EventListeners.js +1 -1
  70. package/umd/Core/Utils/InteractionManager.js +3 -2
  71. package/umd/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
  72. package/umd/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
  73. package/umd/Utils/CanvasUtils.js +14 -14
@@ -41,7 +41,7 @@ function fixOutMode(data) {
41
41
  }
42
42
  }
43
43
  export class Particle {
44
- constructor(engine, id, container, position, overrideOptions, group) {
44
+ constructor(engine, container) {
45
45
  this.container = container;
46
46
  this._calcPosition = (container, position, zIndex, tryCount = defaultRetryCount) => {
47
47
  for (const [, plugin] of container.plugins) {
@@ -56,7 +56,7 @@ export class Particle {
56
56
  }), pos = Vector3d.create(exactPosition.x, exactPosition.y, zIndex), radius = this.getRadius(), outModes = this.options.move.outModes, fixHorizontal = (outMode) => {
57
57
  fixOutMode({
58
58
  outMode,
59
- checkModes: ["bounce", "bounce-horizontal"],
59
+ checkModes: ["bounce"],
60
60
  coord: pos.x,
61
61
  maxCoord: container.canvas.size.width,
62
62
  setCb: (value) => (pos.x += value),
@@ -65,7 +65,7 @@ export class Particle {
65
65
  }, fixVertical = (outMode) => {
66
66
  fixOutMode({
67
67
  outMode,
68
- checkModes: ["bounce", "bounce-vertical"],
68
+ checkModes: ["bounce"],
69
69
  coord: pos.y,
70
70
  maxCoord: container.canvas.size.height,
71
71
  setCb: (value) => (pos.y += value),
@@ -152,7 +152,6 @@ export class Particle {
152
152
  this.offset = Vector.origin;
153
153
  };
154
154
  this._engine = engine;
155
- this.init(id, position, overrideOptions, group);
156
155
  }
157
156
  destroy(override) {
158
157
  if (this.unbreakable || this.destroyed) {
@@ -177,12 +176,12 @@ export class Particle {
177
176
  },
178
177
  });
179
178
  }
180
- draw(delta) {
179
+ async draw(delta) {
181
180
  const container = this.container, canvas = container.canvas;
182
181
  for (const [, plugin] of container.plugins) {
183
- canvas.drawParticlePlugin(plugin, this, delta);
182
+ await canvas.drawParticlePlugin(plugin, this, delta);
184
183
  }
185
- canvas.drawParticle(this, delta);
184
+ await canvas.drawParticle(this, delta);
186
185
  }
187
186
  getFillColor() {
188
187
  return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.color));
@@ -203,7 +202,7 @@ export class Particle {
203
202
  getStrokeColor() {
204
203
  return this._getRollColor(this.bubble.color ?? getHslFromAnimation(this.strokeColor));
205
204
  }
206
- init(id, position, overrideOptions, group) {
205
+ async init(id, position, overrideOptions, group) {
207
206
  const container = this.container, engine = this._engine;
208
207
  this.id = id;
209
208
  this.group = group;
@@ -267,7 +266,7 @@ export class Particle {
267
266
  if (pathOptions.generator) {
268
267
  this.pathGenerator = this._engine.getPathGenerator(pathOptions.generator);
269
268
  if (this.pathGenerator && container.addPath(pathOptions.generator, this.pathGenerator)) {
270
- this.pathGenerator.init(container);
269
+ await this.pathGenerator.init(container);
271
270
  }
272
271
  }
273
272
  container.retina.initParticle(this);
@@ -296,7 +295,7 @@ export class Particle {
296
295
  }
297
296
  }
298
297
  if (effectDrawer?.loadEffect) {
299
- effectDrawer.loadEffect(this);
298
+ await effectDrawer.loadEffect(this);
300
299
  }
301
300
  let shapeDrawer = container.shapeDrawers.get(this.shape);
302
301
  if (!shapeDrawer) {
@@ -306,7 +305,7 @@ export class Particle {
306
305
  }
307
306
  }
308
307
  if (shapeDrawer?.loadShape) {
309
- shapeDrawer.loadShape(this);
308
+ await shapeDrawer.loadShape(this);
310
309
  }
311
310
  const sideCountFunc = shapeDrawer?.getSidesCount;
312
311
  if (sideCountFunc) {
@@ -315,13 +314,13 @@ export class Particle {
315
314
  this.spawning = false;
316
315
  this.shadowColor = rangeColorToRgb(this.options.shadow.color);
317
316
  for (const updater of particles.updaters) {
318
- updater.init(this);
317
+ await updater.init(this);
319
318
  }
320
319
  for (const mover of particles.movers) {
321
- mover.init?.(this);
320
+ await mover.init?.(this);
322
321
  }
323
- effectDrawer?.particleInit?.(container, this);
324
- shapeDrawer?.particleInit?.(container, this);
322
+ await effectDrawer?.particleInit?.(container, this);
323
+ await shapeDrawer?.particleInit?.(container, this);
325
324
  for (const [, plugin] of container.plugins) {
326
325
  plugin.particleCreated?.(this);
327
326
  }
@@ -1,6 +1,5 @@
1
1
  import { getLogger, getPosition } from "../Utils/Utils.js";
2
2
  import { InteractionManager } from "./Utils/InteractionManager.js";
3
- import { Particle } from "./Particle.js";
4
3
  import { Point } from "./Utils/Point.js";
5
4
  import { QuadTree } from "./Utils/QuadTree.js";
6
5
  import { Rectangle } from "./Utils/Rectangle.js";
@@ -17,7 +16,7 @@ export class Particles {
17
16
  this._pool.push(particle);
18
17
  }
19
18
  };
20
- this._applyDensity = (options, manualCount, group) => {
19
+ this._applyDensity = async (options, manualCount, group) => {
21
20
  const numberOptions = options.number;
22
21
  if (!options.number.density?.enable) {
23
22
  if (group === undefined) {
@@ -36,7 +35,7 @@ export class Particles {
36
35
  this._groupLimits.set(group, numberOptions.limit.value * densityFactor);
37
36
  }
38
37
  if (particlesCount < particlesNumber) {
39
- this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
38
+ await this.push(Math.abs(particlesNumber - particlesCount), undefined, options, group);
40
39
  }
41
40
  else if (particlesCount > particlesNumber) {
42
41
  this.removeQuantity(particlesCount - particlesNumber, group);
@@ -50,15 +49,14 @@ export class Particles {
50
49
  const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
51
50
  return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
52
51
  };
53
- this._pushParticle = (position, overrideOptions, group, initializer) => {
52
+ this._pushParticle = async (position, overrideOptions, group, initializer) => {
54
53
  try {
55
54
  let particle = this._pool.pop();
56
- if (particle) {
57
- particle.init(this._nextId, position, overrideOptions, group);
58
- }
59
- else {
60
- particle = new Particle(this._engine, this._nextId, this._container, position, overrideOptions, group);
55
+ if (!particle) {
56
+ const { Particle } = await import("./Particle.js");
57
+ particle = new Particle(this._engine, this._container);
61
58
  }
59
+ await particle.init(this._nextId, position, overrideOptions, group);
62
60
  let canAdd = true;
63
61
  if (initializer) {
64
62
  canAdd = initializer(particle);
@@ -110,21 +108,22 @@ export class Particles {
110
108
  this._needsSort = false;
111
109
  this._lastZIndex = 0;
112
110
  this._interactionManager = new InteractionManager(engine, container);
111
+ this._pluginsInitialized = false;
113
112
  const canvasSize = container.canvas.size;
114
113
  this.quadTree = new QuadTree(qTreeRectangle(canvasSize), qTreeCapacity);
115
- this.movers = this._engine.getMovers(container, true);
116
- this.updaters = this._engine.getUpdaters(container, true);
114
+ this.movers = [];
115
+ this.updaters = [];
117
116
  }
118
117
  get count() {
119
118
  return this._array.length;
120
119
  }
121
- addManualParticles() {
120
+ async addManualParticles() {
122
121
  const container = this._container, options = container.actualOptions;
123
122
  for (const particle of options.manualParticles) {
124
- this.addParticle(particle.position ? getPosition(particle.position, container.canvas.size) : undefined, particle.options);
123
+ await this.addParticle(particle.position ? getPosition(particle.position, container.canvas.size) : undefined, particle.options);
125
124
  }
126
125
  }
127
- addParticle(position, overrideOptions, group, initializer) {
126
+ async addParticle(position, overrideOptions, group, initializer) {
128
127
  const limitOptions = this._container.actualOptions.particles.number.limit, limit = group === undefined ? this._limit : this._groupLimits.get(group) ?? this._limit, currentCount = this.count, minLimit = 0;
129
128
  if (limit > minLimit) {
130
129
  if (limitOptions.mode === "delete") {
@@ -139,11 +138,12 @@ export class Particles {
139
138
  }
140
139
  }
141
140
  }
142
- return this._pushParticle(position, overrideOptions, group, initializer);
141
+ return await this._pushParticle(position, overrideOptions, group, initializer);
143
142
  }
144
143
  clear() {
145
144
  this._array = [];
146
145
  this._zArray = [];
146
+ this._pluginsInitialized = false;
147
147
  }
148
148
  destroy() {
149
149
  this._array = [];
@@ -156,10 +156,10 @@ export class Particles {
156
156
  canvas.clear();
157
157
  await this.update(delta);
158
158
  for (const [, plugin] of container.plugins) {
159
- canvas.drawPlugin(plugin, delta);
159
+ await canvas.drawPlugin(plugin, delta);
160
160
  }
161
161
  for (const p of this._zArray) {
162
- p.draw(delta);
162
+ await p.draw(delta);
163
163
  }
164
164
  }
165
165
  filter(condition) {
@@ -174,13 +174,12 @@ export class Particles {
174
174
  handleClickMode(mode) {
175
175
  this._interactionManager.handleClickMode(mode);
176
176
  }
177
- init() {
177
+ async init() {
178
178
  const container = this._container, options = container.actualOptions;
179
179
  this._lastZIndex = 0;
180
180
  this._needsSort = false;
181
+ await this.initPlugins();
181
182
  let handled = false;
182
- this.updaters = this._engine.getUpdaters(container, true);
183
- this._interactionManager.init();
184
183
  for (const [, plugin] of container.plugins) {
185
184
  if (plugin.particlesInitialization !== undefined) {
186
185
  handled = plugin.particlesInitialization();
@@ -189,32 +188,40 @@ export class Particles {
189
188
  break;
190
189
  }
191
190
  }
192
- this._interactionManager.init();
193
- for (const [, pathGenerator] of container.pathGenerators) {
194
- pathGenerator.init(container);
195
- }
196
- this.addManualParticles();
191
+ await this.addManualParticles();
197
192
  if (!handled) {
198
193
  const particlesOptions = options.particles, groups = particlesOptions.groups;
199
194
  for (const group in groups) {
200
195
  const groupOptions = groups[group];
201
196
  for (let i = this.count, j = 0; j < groupOptions.number?.value && i < particlesOptions.number.value; i++, j++) {
202
- this.addParticle(undefined, groupOptions, group);
197
+ await this.addParticle(undefined, groupOptions, group);
203
198
  }
204
199
  }
205
200
  for (let i = this.count; i < particlesOptions.number.value; i++) {
206
- this.addParticle();
201
+ await this.addParticle();
207
202
  }
208
203
  }
209
204
  }
210
- push(nb, mouse, overrideOptions, group) {
205
+ async initPlugins() {
206
+ if (this._pluginsInitialized) {
207
+ return;
208
+ }
209
+ const container = this._container;
210
+ this.movers = await this._engine.getMovers(container, true);
211
+ this.updaters = await this._engine.getUpdaters(container, true);
212
+ await this._interactionManager.init();
213
+ for (const [, pathGenerator] of container.pathGenerators) {
214
+ await pathGenerator.init(container);
215
+ }
216
+ }
217
+ async push(nb, mouse, overrideOptions, group) {
211
218
  for (let i = 0; i < nb; i++) {
212
- this.addParticle(mouse?.position, overrideOptions, group);
219
+ await this.addParticle(mouse?.position, overrideOptions, group);
213
220
  }
214
221
  }
215
222
  async redraw() {
216
223
  this.clear();
217
- this.init();
224
+ await this.init();
218
225
  await this.draw({ value: 0, factor: 0 });
219
226
  }
220
227
  remove(particle, group, override) {
@@ -236,12 +243,12 @@ export class Particles {
236
243
  const defaultIndex = 0;
237
244
  this.removeAt(defaultIndex, quantity, group);
238
245
  }
239
- setDensity() {
246
+ async setDensity() {
240
247
  const options = this._container.actualOptions, groups = options.particles.groups, manualCount = 0;
241
248
  for (const group in groups) {
242
- this._applyDensity(groups[group], manualCount, group);
249
+ await this._applyDensity(groups[group], manualCount, group);
243
250
  }
244
- this._applyDensity(options.particles, options.manualParticles.length);
251
+ await this._applyDensity(options.particles, options.manualParticles.length);
245
252
  }
246
253
  setLastZIndex(zIndex) {
247
254
  this._lastZIndex = zIndex;
@@ -277,7 +284,7 @@ export class Particles {
277
284
  }
278
285
  for (const mover of this.movers) {
279
286
  if (mover.isEnabled(particle)) {
280
- mover.move(particle, delta);
287
+ await mover.move(particle, delta);
281
288
  }
282
289
  }
283
290
  if (particle.destroyed) {
@@ -303,7 +310,7 @@ export class Particles {
303
310
  await this._interactionManager.externalInteract(delta);
304
311
  for (const particle of this._array) {
305
312
  for (const updater of this.updaters) {
306
- updater.update(particle, delta);
313
+ await updater.update(particle, delta);
307
314
  }
308
315
  if (!particle.destroyed && !particle.spawning) {
309
316
  await this._interactionManager.particlesInteract(particle, delta);
@@ -55,7 +55,7 @@ export class EventListeners {
55
55
  }
56
56
  else {
57
57
  container.pageHidden = false;
58
- if (container.getAnimationStatus()) {
58
+ if (container.animationStatus) {
59
59
  container.play(true);
60
60
  }
61
61
  else {
@@ -2,7 +2,7 @@ export class InteractionManager {
2
2
  constructor(engine, container) {
3
3
  this.container = container;
4
4
  this._engine = engine;
5
- this._interactors = engine.getInteractors(this.container, true);
5
+ this._interactors = [];
6
6
  this._externalInteractors = [];
7
7
  this._particleInteractors = [];
8
8
  }
@@ -18,7 +18,8 @@ export class InteractionManager {
18
18
  interactor.handleClickMode?.(mode);
19
19
  }
20
20
  }
21
- init() {
21
+ async init() {
22
+ this._interactors = await this._engine.getInteractors(this.container, true);
22
23
  this._externalInteractors = [];
23
24
  this._particleInteractors = [];
24
25
  for (const interactor of this._interactors) {
@@ -15,7 +15,7 @@ export class BackgroundMask {
15
15
  }
16
16
  if (data.cover !== undefined) {
17
17
  const cover = data.cover, color = (isString(data.cover) ? { color: data.cover } : data.cover);
18
- this.cover.load(cover.color !== undefined ? cover : { color: color });
18
+ this.cover.load(cover.color !== undefined || cover.image !== undefined ? cover : { color: color });
19
19
  }
20
20
  if (data.enable !== undefined) {
21
21
  this.enable = data.enable;
@@ -1,8 +1,6 @@
1
1
  import { OptionsColor } from "../OptionsColor.js";
2
2
  export class BackgroundMaskCover {
3
3
  constructor() {
4
- this.color = new OptionsColor();
5
- this.color.value = "#fff";
6
4
  this.opacity = 1;
7
5
  }
8
6
  load(data) {
@@ -12,6 +10,9 @@ export class BackgroundMaskCover {
12
10
  if (data.color !== undefined) {
13
11
  this.color = OptionsColor.create(this.color, data.color);
14
12
  }
13
+ if (data.image !== undefined) {
14
+ this.image = data.image;
15
+ }
15
16
  if (data.opacity !== undefined) {
16
17
  this.opacity = data.opacity;
17
18
  }
@@ -21,7 +21,7 @@ export function paintImage(context, dimension, image, opacity) {
21
21
  export function clear(context, dimension) {
22
22
  context.clearRect(origin.x, origin.y, dimension.width, dimension.height);
23
23
  }
24
- export function drawParticle(data) {
24
+ export async function drawParticle(data) {
25
25
  const { container, context, particle, delta, colorStyles, backgroundMask, composite, radius, opacity, shadow, transform, } = data, pos = particle.getPosition(), defaultAngle = 0, angle = particle.rotation + (particle.pathRotation ? particle.velocity.angle : defaultAngle), rotateData = {
26
26
  sin: Math.sin(angle),
27
27
  cos: Math.cos(angle),
@@ -60,13 +60,13 @@ export function drawParticle(data) {
60
60
  transformData,
61
61
  strokeWidth,
62
62
  };
63
- drawShape(drawData);
64
- drawShapeAfterDraw(drawData);
65
- drawEffect(drawData);
63
+ await drawShape(drawData);
64
+ await drawShapeAfterDraw(drawData);
65
+ await drawEffect(drawData);
66
66
  context.globalCompositeOperation = "source-over";
67
67
  context.resetTransform();
68
68
  }
69
- export function drawEffect(data) {
69
+ export async function drawEffect(data) {
70
70
  const { container, context, particle, radius, opacity, delta, transformData } = data;
71
71
  if (!particle.effect) {
72
72
  return;
@@ -75,7 +75,7 @@ export function drawEffect(data) {
75
75
  if (!drawer) {
76
76
  return;
77
77
  }
78
- drawer.draw({
78
+ await drawer.draw({
79
79
  context,
80
80
  particle,
81
81
  radius,
@@ -85,7 +85,7 @@ export function drawEffect(data) {
85
85
  transformData: { ...transformData },
86
86
  });
87
87
  }
88
- export function drawShape(data) {
88
+ export async function drawShape(data) {
89
89
  const { container, context, particle, radius, opacity, delta, strokeWidth, transformData } = data, minStrokeWidth = 0;
90
90
  if (!particle.shape) {
91
91
  return;
@@ -95,7 +95,7 @@ export function drawShape(data) {
95
95
  return;
96
96
  }
97
97
  context.beginPath();
98
- drawer.draw({
98
+ await drawer.draw({
99
99
  context,
100
100
  particle,
101
101
  radius,
@@ -114,7 +114,7 @@ export function drawShape(data) {
114
114
  context.fill();
115
115
  }
116
116
  }
117
- export function drawShapeAfterDraw(data) {
117
+ export async function drawShapeAfterDraw(data) {
118
118
  const { container, context, particle, radius, opacity, delta, transformData } = data;
119
119
  if (!particle.shape) {
120
120
  return;
@@ -123,7 +123,7 @@ export function drawShapeAfterDraw(data) {
123
123
  if (!drawer?.afterDraw) {
124
124
  return;
125
125
  }
126
- drawer.afterDraw({
126
+ await drawer.afterDraw({
127
127
  context,
128
128
  particle,
129
129
  radius,
@@ -133,17 +133,17 @@ export function drawShapeAfterDraw(data) {
133
133
  transformData: { ...transformData },
134
134
  });
135
135
  }
136
- export function drawPlugin(context, plugin, delta) {
136
+ export async function drawPlugin(context, plugin, delta) {
137
137
  if (!plugin.draw) {
138
138
  return;
139
139
  }
140
- plugin.draw(context, delta);
140
+ await plugin.draw(context, delta);
141
141
  }
142
- export function drawParticlePlugin(context, plugin, particle, delta) {
142
+ export async function drawParticlePlugin(context, plugin, particle, delta) {
143
143
  if (!plugin.drawParticle) {
144
144
  return;
145
145
  }
146
- plugin.drawParticle(context, particle, delta);
146
+ await plugin.drawParticle(context, particle, delta);
147
147
  }
148
148
  export function alterHsl(color, type, value) {
149
149
  const lFactor = 1;
@@ -11,6 +11,26 @@ function setTransformValue(factor, newFactor, key) {
11
11
  factor[key] = (factor[key] ?? defaultValue) * newValue;
12
12
  }
13
13
  }
14
+ function setStyle(canvas, style, important = false) {
15
+ if (!style) {
16
+ return;
17
+ }
18
+ const element = canvas;
19
+ if (!element) {
20
+ return;
21
+ }
22
+ const elementStyle = element.style;
23
+ if (!elementStyle) {
24
+ return;
25
+ }
26
+ for (const key in style) {
27
+ const value = style[key];
28
+ if (!value) {
29
+ continue;
30
+ }
31
+ elementStyle.setProperty(key, value, important ? "important" : "");
32
+ }
33
+ }
14
34
  class Canvas {
15
35
  constructor(container) {
16
36
  this.container = container;
@@ -59,14 +79,36 @@ class Canvas {
59
79
  }
60
80
  return [fColor, sColor];
61
81
  };
62
- this._initCover = () => {
63
- const options = this.container.actualOptions, cover = options.backgroundMask.cover, color = cover.color, coverRgb = (0, ColorUtils_js_1.rangeColorToRgb)(color);
64
- if (coverRgb) {
65
- const coverColor = {
66
- ...coverRgb,
67
- a: cover.opacity,
68
- };
69
- this._coverColorStyle = (0, ColorUtils_js_1.getStyleFromRgb)(coverColor, coverColor.a);
82
+ this._initCover = async () => {
83
+ const options = this.container.actualOptions, cover = options.backgroundMask.cover, color = cover.color;
84
+ if (color) {
85
+ const coverRgb = (0, ColorUtils_js_1.rangeColorToRgb)(color);
86
+ if (coverRgb) {
87
+ const coverColor = {
88
+ ...coverRgb,
89
+ a: cover.opacity,
90
+ };
91
+ this._coverColorStyle = (0, ColorUtils_js_1.getStyleFromRgb)(coverColor, coverColor.a);
92
+ }
93
+ }
94
+ else {
95
+ await new Promise((resolve, reject) => {
96
+ if (!cover.image) {
97
+ return;
98
+ }
99
+ const img = document.createElement("img");
100
+ img.addEventListener("load", () => {
101
+ this._coverImage = {
102
+ image: img,
103
+ opacity: cover.opacity,
104
+ };
105
+ resolve();
106
+ });
107
+ img.addEventListener("error", (evt) => {
108
+ reject(evt.error);
109
+ });
110
+ img.src = cover.image;
111
+ });
70
112
  }
71
113
  };
72
114
  this._initStyle = () => {
@@ -151,13 +193,7 @@ class Canvas {
151
193
  if (!(element && originalStyle)) {
152
194
  return;
153
195
  }
154
- const style = element.style;
155
- style.position = originalStyle.position;
156
- style.zIndex = originalStyle.zIndex;
157
- style.top = originalStyle.top;
158
- style.left = originalStyle.left;
159
- style.width = originalStyle.width;
160
- style.height = originalStyle.height;
196
+ setStyle(element, originalStyle);
161
197
  };
162
198
  this._safeMutationObserver = (callback) => {
163
199
  if (!this._mutationObserver) {
@@ -170,13 +206,15 @@ class Canvas {
170
206
  if (!element) {
171
207
  return;
172
208
  }
173
- const priority = "important", style = element.style, radix = 10;
174
- style.setProperty("position", "fixed", priority);
175
- style.setProperty("z-index", this.container.actualOptions.fullScreen.zIndex.toString(radix), priority);
176
- style.setProperty("top", "0", priority);
177
- style.setProperty("left", "0", priority);
178
- style.setProperty("width", "100%", priority);
179
- style.setProperty("height", "100%", priority);
209
+ const radix = 10;
210
+ setStyle(element, {
211
+ position: "fixed",
212
+ zIndex: this.container.actualOptions.fullScreen.zIndex.toString(radix),
213
+ top: "0",
214
+ left: "0",
215
+ width: "100%",
216
+ height: "100%",
217
+ }, true);
180
218
  };
181
219
  this.size = {
182
220
  height: 0,
@@ -232,7 +270,14 @@ class Canvas {
232
270
  }
233
271
  return cb(ctx);
234
272
  }
235
- drawParticle(particle, delta) {
273
+ drawAsync(cb) {
274
+ const ctx = this._context;
275
+ if (!ctx) {
276
+ return Promise.resolve(undefined);
277
+ }
278
+ return cb(ctx);
279
+ }
280
+ async drawParticle(particle, delta) {
236
281
  if (particle.spawning || particle.destroyed) {
237
282
  return;
238
283
  }
@@ -251,13 +296,13 @@ class Canvas {
251
296
  if (!fColor && !sColor) {
252
297
  return;
253
298
  }
254
- this.draw((ctx) => {
299
+ await this.drawAsync(async (ctx) => {
255
300
  const container = this.container, options = container.actualOptions, zIndexOptions = particle.options.zIndex, zIndexFactorOffset = 1, zIndexFactor = zIndexFactorOffset - particle.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, defaultOpacity = 1, opacity = particle.bubble.opacity ?? particle.opacity?.value ?? defaultOpacity, strokeOpacity = particle.strokeOpacity ?? opacity, zOpacity = opacity * zOpacityFactor, zStrokeOpacity = strokeOpacity * zOpacityFactor, transform = {}, colorStyles = {
256
301
  fill: fColor ? (0, ColorUtils_js_1.getStyleFromHsl)(fColor, zOpacity) : undefined,
257
302
  };
258
303
  colorStyles.stroke = sColor ? (0, ColorUtils_js_1.getStyleFromHsl)(sColor, zStrokeOpacity) : colorStyles.fill;
259
304
  this._applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform);
260
- (0, CanvasUtils_js_1.drawParticle)({
305
+ await (0, CanvasUtils_js_1.drawParticle)({
261
306
  container,
262
307
  context: ctx,
263
308
  particle,
@@ -273,11 +318,11 @@ class Canvas {
273
318
  this._applyPostDrawUpdaters(particle);
274
319
  });
275
320
  }
276
- drawParticlePlugin(plugin, particle, delta) {
277
- this.draw((ctx) => (0, CanvasUtils_js_1.drawParticlePlugin)(ctx, plugin, particle, delta));
321
+ async drawParticlePlugin(plugin, particle, delta) {
322
+ await this.drawAsync((ctx) => (0, CanvasUtils_js_1.drawParticlePlugin)(ctx, plugin, particle, delta));
278
323
  }
279
- drawPlugin(plugin, delta) {
280
- this.draw((ctx) => (0, CanvasUtils_js_1.drawPlugin)(ctx, plugin, delta));
324
+ async drawPlugin(plugin, delta) {
325
+ await this.drawAsync((ctx) => (0, CanvasUtils_js_1.drawPlugin)(ctx, plugin, delta));
281
326
  }
282
327
  async init() {
283
328
  this._safeMutationObserver((obs) => obs.disconnect());
@@ -290,7 +335,7 @@ class Canvas {
290
335
  });
291
336
  this.resize();
292
337
  this._initStyle();
293
- this._initCover();
338
+ await this._initCover();
294
339
  try {
295
340
  await this._initTrail();
296
341
  }
@@ -380,7 +425,15 @@ class Canvas {
380
425
  this.draw((ctx) => {
381
426
  if (options.backgroundMask.enable && options.backgroundMask.cover) {
382
427
  (0, CanvasUtils_js_1.clear)(ctx, this.size);
383
- this._paintBase(this._coverColorStyle);
428
+ if (this._coverImage) {
429
+ this._paintImage(this._coverImage.image, this._coverImage.opacity);
430
+ }
431
+ else if (this._coverColorStyle) {
432
+ this._paintBase(this._coverColorStyle);
433
+ }
434
+ else {
435
+ this._paintBase();
436
+ }
384
437
  }
385
438
  else {
386
439
  this._paintBase();
@@ -422,7 +475,7 @@ class Canvas {
422
475
  return;
423
476
  }
424
477
  const container = this.container, needsRefresh = container.updateActualOptions();
425
- container.particles.setDensity();
478
+ await container.particles.setDensity();
426
479
  this._applyResizePlugins();
427
480
  if (needsRefresh) {
428
481
  await container.refresh();