@tsparticles/plugin-emitters 4.0.0-alpha.2 → 4.0.0-alpha.21
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.
- package/278.min.js +1 -0
- package/615.min.js +1 -0
- package/751.min.js +1 -0
- package/816.min.js +1 -0
- package/88.min.js +1 -0
- package/975.min.js +1 -0
- package/README.md +5 -0
- package/browser/EmitterInstance.js +69 -47
- package/browser/EmitterShapeBase.js +4 -0
- package/browser/EmittersInstancesManager.js +71 -0
- package/browser/EmittersInteractor.js +114 -0
- package/browser/EmittersPlugin.js +10 -56
- package/browser/EmittersPluginInstance.js +44 -0
- package/browser/Options/Classes/Emitter.js +13 -0
- package/browser/Options/Classes/EmitterLife.js +4 -0
- package/browser/Options/Classes/EmitterRate.js +2 -0
- package/browser/Options/Classes/EmitterShape.js +3 -0
- package/browser/Options/Classes/EmitterShapeReplace.js +2 -0
- package/browser/Options/Classes/EmitterSize.js +3 -0
- package/browser/ShapeManager.js +4 -4
- package/browser/constants.js +4 -0
- package/browser/index.js +20 -6
- package/cjs/EmitterInstance.js +69 -47
- package/cjs/EmitterShapeBase.js +4 -0
- package/cjs/EmittersInstancesManager.js +71 -0
- package/cjs/EmittersInteractor.js +114 -0
- package/cjs/EmittersPlugin.js +10 -56
- package/cjs/EmittersPluginInstance.js +44 -0
- package/cjs/Options/Classes/Emitter.js +13 -0
- package/cjs/Options/Classes/EmitterLife.js +4 -0
- package/cjs/Options/Classes/EmitterRate.js +2 -0
- package/cjs/Options/Classes/EmitterShape.js +3 -0
- package/cjs/Options/Classes/EmitterShapeReplace.js +2 -0
- package/cjs/Options/Classes/EmitterSize.js +3 -0
- package/cjs/ShapeManager.js +4 -4
- package/cjs/constants.js +4 -0
- package/cjs/index.js +20 -6
- package/dist_browser_EmitterInstance_js.js +30 -0
- package/dist_browser_EmittersInstancesManager_js.js +90 -0
- package/dist_browser_EmittersInteractor_js.js +100 -0
- package/dist_browser_EmittersPluginInstance_js.js +30 -0
- package/dist_browser_EmittersPlugin_js.js +8 -28
- package/dist_browser_ShapeManager_js.js +2 -2
- package/esm/EmitterInstance.js +69 -47
- package/esm/EmitterShapeBase.js +4 -0
- package/esm/EmittersInstancesManager.js +71 -0
- package/esm/EmittersInteractor.js +114 -0
- package/esm/EmittersPlugin.js +10 -56
- package/esm/EmittersPluginInstance.js +44 -0
- package/esm/Options/Classes/Emitter.js +13 -0
- package/esm/Options/Classes/EmitterLife.js +4 -0
- package/esm/Options/Classes/EmitterRate.js +2 -0
- package/esm/Options/Classes/EmitterShape.js +3 -0
- package/esm/Options/Classes/EmitterShapeReplace.js +2 -0
- package/esm/Options/Classes/EmitterSize.js +3 -0
- package/esm/ShapeManager.js +4 -4
- package/esm/constants.js +4 -0
- package/esm/index.js +20 -6
- package/package.json +3 -2
- package/report.html +3 -3
- package/tsparticles.plugin.emitters.js +58 -18
- package/tsparticles.plugin.emitters.min.js +2 -2
- package/types/EmitterContainer.d.ts +8 -7
- package/types/EmitterInstance.d.ts +2 -3
- package/types/EmittersEngine.d.ts +2 -2
- package/types/EmittersInstancesManager.d.ts +15 -0
- package/types/EmittersInteractor.d.ts +18 -0
- package/types/EmittersPlugin.d.ts +7 -8
- package/types/EmittersPluginInstance.d.ts +14 -0
- package/types/IEmitterShapeGenerator.d.ts +2 -2
- package/types/constants.d.ts +2 -0
- package/types/index.d.ts +3 -2
- package/types/types.d.ts +15 -9
- package/umd/EmitterInstance.js +69 -47
- package/umd/EmitterShapeBase.js +4 -0
- package/umd/EmittersInstancesManager.js +119 -0
- package/umd/EmittersInteractor.js +128 -0
- package/umd/EmittersPlugin.js +44 -56
- package/umd/EmittersPluginInstance.js +58 -0
- package/umd/Options/Classes/Emitter.js +13 -0
- package/umd/Options/Classes/EmitterLife.js +4 -0
- package/umd/Options/Classes/EmitterRate.js +2 -0
- package/umd/Options/Classes/EmitterShape.js +3 -0
- package/umd/Options/Classes/EmitterShapeReplace.js +2 -0
- package/umd/Options/Classes/EmitterSize.js +3 -0
- package/umd/ShapeManager.js +4 -4
- package/umd/constants.js +17 -0
- package/umd/index.js +21 -6
- package/214.min.js +0 -2
- package/214.min.js.LICENSE.txt +0 -1
- package/921.min.js +0 -2
- package/921.min.js.LICENSE.txt +0 -1
- package/browser/Emitters.js +0 -128
- package/cjs/Emitters.js +0 -128
- package/esm/Emitters.js +0 -128
- package/tsparticles.plugin.emitters.min.js.LICENSE.txt +0 -1
- package/types/Emitters.d.ts +0 -24
- package/umd/Emitters.js +0 -142
package/esm/EmitterInstance.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PixelMode, Vector, calcPositionOrRandomFromSizeRanged, deepExtend, getRangeValue, getSize, hMax, half, isPointInside, itemFromSingleOrMultiple, lMax, millisecondsToSeconds, randomInRangeValue, rangeColorToHsl, sMax, safeDocument, } from "@tsparticles/engine";
|
|
2
2
|
import { Emitter } from "./Options/Classes/Emitter.js";
|
|
3
3
|
import { EmitterSize } from "./Options/Classes/EmitterSize.js";
|
|
4
|
-
const defaultLifeDelay = 0, minLifeCount = 0, defaultSpawnDelay = 0, defaultEmitDelay = 0, defaultLifeCount = -1, defaultColorAnimationFactor = 1;
|
|
4
|
+
const defaultLifeDelay = 0, minLifeCount = 0, defaultSpawnDelay = 0, defaultEmitDelay = 0, defaultLifeCount = -1, defaultColorAnimationFactor = 1, colorFactor = 3.6;
|
|
5
5
|
function setParticlesOptionsColor(particlesOptions, color) {
|
|
6
6
|
if (particlesOptions.color) {
|
|
7
7
|
particlesOptions.color.value = color;
|
|
@@ -13,41 +13,35 @@ function setParticlesOptionsColor(particlesOptions, color) {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
export class EmitterInstance {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
container;
|
|
17
|
+
removeCallback;
|
|
18
|
+
fill;
|
|
19
|
+
name;
|
|
20
|
+
options;
|
|
21
|
+
position;
|
|
22
|
+
size;
|
|
23
|
+
spawnColor;
|
|
24
|
+
_currentDuration;
|
|
25
|
+
_currentEmitDelay;
|
|
26
|
+
_currentSpawnDelay;
|
|
27
|
+
_duration;
|
|
28
|
+
_emitDelay;
|
|
29
|
+
_engine;
|
|
30
|
+
_firstSpawn;
|
|
31
|
+
_immortal;
|
|
32
|
+
_initialPosition;
|
|
33
|
+
_lifeCount;
|
|
34
|
+
_mutationObserver;
|
|
35
|
+
_particlesOptions;
|
|
36
|
+
_paused;
|
|
37
|
+
_resizeObserver;
|
|
38
|
+
_shape;
|
|
39
|
+
_size;
|
|
40
|
+
_spawnDelay;
|
|
41
|
+
_startParticlesAdded;
|
|
42
|
+
constructor(engine, container, removeCallback, options, position) {
|
|
18
43
|
this.container = container;
|
|
19
|
-
this.
|
|
20
|
-
this._mutationObserver?.disconnect();
|
|
21
|
-
this._mutationObserver = undefined;
|
|
22
|
-
this._resizeObserver?.disconnect();
|
|
23
|
-
this._resizeObserver = undefined;
|
|
24
|
-
this.emitters.removeEmitter(this);
|
|
25
|
-
this._engine.dispatchEvent("emitterDestroyed", {
|
|
26
|
-
container: this.container,
|
|
27
|
-
data: {
|
|
28
|
-
emitter: this,
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
this._prepareToDie = () => {
|
|
33
|
-
if (this._paused) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const duration = this.options.life.duration !== undefined ? getRangeValue(this.options.life.duration) : undefined, minDuration = 0, minLifeCount = 0;
|
|
37
|
-
if ((this._lifeCount > minLifeCount || this._immortal) && duration !== undefined && duration > minDuration) {
|
|
38
|
-
this._duration = duration * millisecondsToSeconds;
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
this._setColorAnimation = (animation, initValue, maxValue, factor = defaultColorAnimationFactor) => {
|
|
42
|
-
const container = this.container;
|
|
43
|
-
if (!animation.enable) {
|
|
44
|
-
return initValue;
|
|
45
|
-
}
|
|
46
|
-
const colorOffset = randomInRangeValue(animation.offset), delay = getRangeValue(this.options.rate.delay), emitFactor = container.retina.reduceFactor
|
|
47
|
-
? (delay * millisecondsToSeconds) / container.retina.reduceFactor
|
|
48
|
-
: Infinity, colorSpeed = getRangeValue(animation.speed);
|
|
49
|
-
return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
|
|
50
|
-
};
|
|
44
|
+
this.removeCallback = removeCallback;
|
|
51
45
|
this._engine = engine;
|
|
52
46
|
this._currentDuration = 0;
|
|
53
47
|
this._currentEmitDelay = 0;
|
|
@@ -99,7 +93,7 @@ export class EmitterInstance {
|
|
|
99
93
|
}
|
|
100
94
|
const shapeOptions = this.options.shape, shapeGenerator = this._engine.emitterShapeManager?.getShapeGenerator(shapeOptions.type);
|
|
101
95
|
if (shapeGenerator) {
|
|
102
|
-
this._shape = shapeGenerator.generate(this.position, this.size, this.fill, shapeOptions.options);
|
|
96
|
+
this._shape = shapeGenerator.generate(this.container, this.position, this.size, this.fill, shapeOptions.options);
|
|
103
97
|
}
|
|
104
98
|
this._engine.dispatchEvent("emitterCreated", {
|
|
105
99
|
container,
|
|
@@ -201,7 +195,7 @@ export class EmitterInstance {
|
|
|
201
195
|
container: this.container,
|
|
202
196
|
});
|
|
203
197
|
this.play();
|
|
204
|
-
this._currentSpawnDelay -= this.
|
|
198
|
+
this._currentSpawnDelay -= this._spawnDelay;
|
|
205
199
|
delete this._spawnDelay;
|
|
206
200
|
}
|
|
207
201
|
}
|
|
@@ -254,6 +248,19 @@ export class EmitterInstance {
|
|
|
254
248
|
return size;
|
|
255
249
|
})());
|
|
256
250
|
}
|
|
251
|
+
_destroy = () => {
|
|
252
|
+
this._mutationObserver?.disconnect();
|
|
253
|
+
this._mutationObserver = undefined;
|
|
254
|
+
this._resizeObserver?.disconnect();
|
|
255
|
+
this._resizeObserver = undefined;
|
|
256
|
+
this.removeCallback(this);
|
|
257
|
+
this._engine.dispatchEvent("emitterDestroyed", {
|
|
258
|
+
container: this.container,
|
|
259
|
+
data: {
|
|
260
|
+
emitter: this,
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
};
|
|
257
264
|
_emit() {
|
|
258
265
|
if (this._paused) {
|
|
259
266
|
return;
|
|
@@ -262,24 +269,20 @@ export class EmitterInstance {
|
|
|
262
269
|
this._emitParticles(quantity);
|
|
263
270
|
}
|
|
264
271
|
_emitParticles(quantity) {
|
|
265
|
-
const singleParticlesOptions = itemFromSingleOrMultiple(this._particlesOptions)
|
|
272
|
+
const singleParticlesOptions = (itemFromSingleOrMultiple(this._particlesOptions) ??
|
|
273
|
+
{}), hslAnimation = this.options.spawnColor?.animation, reduceFactor = this.container.retina.reduceFactor, needsColorAnimation = !!hslAnimation, needsShapeData = !!this._shape, needsCopy = needsColorAnimation || needsShapeData, maxValues = needsColorAnimation ? { h: hMax, s: sMax, l: lMax } : null, shapeOptions = this.options.shape;
|
|
266
274
|
for (let i = 0; i < quantity * reduceFactor; i++) {
|
|
267
|
-
const particlesOptions =
|
|
275
|
+
const particlesOptions = needsCopy
|
|
276
|
+
? deepExtend({}, singleParticlesOptions)
|
|
277
|
+
: singleParticlesOptions;
|
|
268
278
|
if (this.spawnColor) {
|
|
269
|
-
|
|
270
|
-
if (hslAnimation) {
|
|
271
|
-
const maxValues = {
|
|
272
|
-
h: hMax,
|
|
273
|
-
s: sMax,
|
|
274
|
-
l: lMax,
|
|
275
|
-
}, colorFactor = 3.6;
|
|
279
|
+
if (hslAnimation && maxValues) {
|
|
276
280
|
this.spawnColor.h = this._setColorAnimation(hslAnimation.h, this.spawnColor.h, maxValues.h, colorFactor);
|
|
277
281
|
this.spawnColor.s = this._setColorAnimation(hslAnimation.s, this.spawnColor.s, maxValues.s);
|
|
278
282
|
this.spawnColor.l = this._setColorAnimation(hslAnimation.l, this.spawnColor.l, maxValues.l);
|
|
279
283
|
}
|
|
280
284
|
setParticlesOptionsColor(particlesOptions, this.spawnColor);
|
|
281
285
|
}
|
|
282
|
-
const shapeOptions = this.options.shape;
|
|
283
286
|
let position = this.position;
|
|
284
287
|
if (this._shape) {
|
|
285
288
|
const shapePosData = this._shape.randomPosition();
|
|
@@ -309,4 +312,23 @@ export class EmitterInstance {
|
|
|
309
312
|
}
|
|
310
313
|
}
|
|
311
314
|
}
|
|
315
|
+
_prepareToDie = () => {
|
|
316
|
+
if (this._paused) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const duration = this.options.life.duration !== undefined ? getRangeValue(this.options.life.duration) : undefined, minDuration = 0, minLifeCount = 0;
|
|
320
|
+
if ((this._lifeCount > minLifeCount || this._immortal) && duration !== undefined && duration > minDuration) {
|
|
321
|
+
this._duration = duration * millisecondsToSeconds;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
_setColorAnimation = (animation, initValue, maxValue, factor = defaultColorAnimationFactor) => {
|
|
325
|
+
const container = this.container;
|
|
326
|
+
if (!animation.enable) {
|
|
327
|
+
return initValue;
|
|
328
|
+
}
|
|
329
|
+
const colorOffset = randomInRangeValue(animation.offset), delay = getRangeValue(this.options.rate.delay), emitFactor = container.retina.reduceFactor
|
|
330
|
+
? (delay * millisecondsToSeconds) / container.retina.reduceFactor
|
|
331
|
+
: Infinity, colorSpeed = getRangeValue(animation.speed);
|
|
332
|
+
return (initValue + (colorSpeed * container.fpsLimit) / emitFactor + colorOffset * factor) % maxValue;
|
|
333
|
+
};
|
|
312
334
|
}
|
package/esm/EmitterShapeBase.js
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { isNumber } from "@tsparticles/engine";
|
|
2
|
+
import { Emitter } from "./Options/Classes/Emitter.js";
|
|
3
|
+
const defaultIndex = 0;
|
|
4
|
+
export class EmittersInstancesManager {
|
|
5
|
+
_containerArrays;
|
|
6
|
+
_engine;
|
|
7
|
+
constructor(engine) {
|
|
8
|
+
this._containerArrays = new Map();
|
|
9
|
+
this._engine = engine;
|
|
10
|
+
}
|
|
11
|
+
async addEmitter(container, options, position) {
|
|
12
|
+
const emitterOptions = new Emitter();
|
|
13
|
+
emitterOptions.load(options);
|
|
14
|
+
const { EmitterInstance } = await import("./EmitterInstance.js"), emitter = new EmitterInstance(this._engine, container, (emitter) => {
|
|
15
|
+
this.removeEmitter(container, emitter);
|
|
16
|
+
}, emitterOptions, position);
|
|
17
|
+
await emitter.init();
|
|
18
|
+
this.getArray(container).push(emitter);
|
|
19
|
+
return emitter;
|
|
20
|
+
}
|
|
21
|
+
clear(container) {
|
|
22
|
+
this.initContainer(container);
|
|
23
|
+
this._containerArrays.set(container, []);
|
|
24
|
+
}
|
|
25
|
+
getArray(container) {
|
|
26
|
+
this.initContainer(container);
|
|
27
|
+
let array = this._containerArrays.get(container);
|
|
28
|
+
if (!array) {
|
|
29
|
+
array = [];
|
|
30
|
+
this._containerArrays.set(container, array);
|
|
31
|
+
}
|
|
32
|
+
return array;
|
|
33
|
+
}
|
|
34
|
+
initContainer(container) {
|
|
35
|
+
if (this._containerArrays.has(container)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this._containerArrays.set(container, []);
|
|
39
|
+
container.getEmitter = (idxOrName) => {
|
|
40
|
+
const array = this.getArray(container);
|
|
41
|
+
return idxOrName === undefined || isNumber(idxOrName)
|
|
42
|
+
? array[idxOrName ?? defaultIndex]
|
|
43
|
+
: array.find(t => t.name === idxOrName);
|
|
44
|
+
};
|
|
45
|
+
container.addEmitter = async (options, position) => this.addEmitter(container, options, position);
|
|
46
|
+
container.removeEmitter = (idxOrName) => {
|
|
47
|
+
const emitter = container.getEmitter?.(idxOrName);
|
|
48
|
+
if (emitter) {
|
|
49
|
+
this.removeEmitter(container, emitter);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
container.playEmitter = (idxOrName) => {
|
|
53
|
+
const emitter = container.getEmitter?.(idxOrName);
|
|
54
|
+
if (emitter) {
|
|
55
|
+
emitter.externalPlay();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
container.pauseEmitter = (idxOrName) => {
|
|
59
|
+
const emitter = container.getEmitter?.(idxOrName);
|
|
60
|
+
if (emitter) {
|
|
61
|
+
emitter.externalPause();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
removeEmitter(container, emitter) {
|
|
66
|
+
const index = this.getArray(container).indexOf(emitter), minIndex = 0, deleteCount = 1;
|
|
67
|
+
if (index >= minIndex) {
|
|
68
|
+
this.getArray(container).splice(index, deleteCount);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ExternalInteractorBase, } from "@tsparticles/plugin-interactivity";
|
|
2
|
+
import { arrayRandomIndex, executeOnSingleOrMultiple, isArray, isInArray, itemFromArray, } from "@tsparticles/engine";
|
|
3
|
+
import { Emitter } from "./Options/Classes/Emitter.js";
|
|
4
|
+
import { defaultRandomOptions } from "./constants.js";
|
|
5
|
+
const emittersMode = "emitters";
|
|
6
|
+
export class EmittersInteractor extends ExternalInteractorBase {
|
|
7
|
+
handleClickMode;
|
|
8
|
+
_instancesManager;
|
|
9
|
+
constructor(instancesManager, container) {
|
|
10
|
+
super(container);
|
|
11
|
+
this._instancesManager = instancesManager;
|
|
12
|
+
this.handleClickMode = (mode, interactivityData) => {
|
|
13
|
+
const container = this.container, options = container.actualOptions, modeEmitters = options.interactivity.modes.emitters;
|
|
14
|
+
if (!modeEmitters || mode !== emittersMode) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let emittersModeOptions;
|
|
18
|
+
if (isArray(modeEmitters.value)) {
|
|
19
|
+
const minLength = 0, modeEmittersCount = modeEmitters.value.length;
|
|
20
|
+
if (modeEmittersCount > minLength && modeEmitters.random.enable) {
|
|
21
|
+
emittersModeOptions = [];
|
|
22
|
+
const usedIndexes = new Set();
|
|
23
|
+
for (let i = 0; i < modeEmitters.random.count; i++) {
|
|
24
|
+
const idx = arrayRandomIndex(modeEmitters.value);
|
|
25
|
+
if (usedIndexes.has(idx) && usedIndexes.size < modeEmittersCount) {
|
|
26
|
+
i--;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
usedIndexes.add(idx);
|
|
30
|
+
const selectedOptions = itemFromArray(modeEmitters.value, idx);
|
|
31
|
+
if (!selectedOptions) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
emittersModeOptions.push(selectedOptions);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
emittersModeOptions = modeEmitters.value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
emittersModeOptions = modeEmitters.value;
|
|
43
|
+
}
|
|
44
|
+
const emittersOptions = emittersModeOptions, ePosition = interactivityData.mouse.clickPosition;
|
|
45
|
+
void executeOnSingleOrMultiple(emittersOptions, async (emitter) => {
|
|
46
|
+
await this._instancesManager.addEmitter(this.container, emitter, ePosition);
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
clear() {
|
|
51
|
+
}
|
|
52
|
+
init() {
|
|
53
|
+
}
|
|
54
|
+
interact(_interactivityData, delta) {
|
|
55
|
+
for (const emitter of this._instancesManager.getArray(this.container)) {
|
|
56
|
+
emitter.update(delta);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
isEnabled(interactivityData, particle) {
|
|
60
|
+
const container = this.container, options = container.actualOptions, mouse = interactivityData.mouse, events = (particle?.interactivity ?? options.interactivity).events;
|
|
61
|
+
if (!mouse.clickPosition || !events.onClick.enable) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return isInArray(emittersMode, events.onClick.mode);
|
|
65
|
+
}
|
|
66
|
+
loadModeOptions(options, ...sources) {
|
|
67
|
+
options.emitters = {
|
|
68
|
+
random: defaultRandomOptions,
|
|
69
|
+
value: [],
|
|
70
|
+
};
|
|
71
|
+
for (const source of sources) {
|
|
72
|
+
if (!source?.emitters) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (isArray(source.emitters)) {
|
|
76
|
+
for (const emitter of source.emitters) {
|
|
77
|
+
const tmp = new Emitter();
|
|
78
|
+
tmp.load(emitter);
|
|
79
|
+
options.emitters.value.push(tmp);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if (Object.hasOwn(source.emitters, "value")) {
|
|
83
|
+
const emitterModeOptions = source.emitters;
|
|
84
|
+
options.emitters.random.enable = emitterModeOptions.random?.enable ?? options.emitters.random.enable;
|
|
85
|
+
options.emitters.random.count = emitterModeOptions.random?.count ?? options.emitters.random.count;
|
|
86
|
+
if (isArray(emitterModeOptions.value)) {
|
|
87
|
+
for (const emitter of emitterModeOptions.value) {
|
|
88
|
+
const tmp = new Emitter();
|
|
89
|
+
tmp.load(emitter);
|
|
90
|
+
options.emitters.value.push(tmp);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const tmp = new Emitter();
|
|
95
|
+
tmp.load(emitterModeOptions.value);
|
|
96
|
+
options.emitters.value.push(tmp);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const tmp = new Emitter();
|
|
101
|
+
tmp.load(source.emitters);
|
|
102
|
+
options.emitters.value.push(tmp);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
removeEmitter(emitter) {
|
|
107
|
+
const index = this._instancesManager.getArray(this.container).indexOf(emitter), minIndex = 0, deleteCount = 1;
|
|
108
|
+
if (index >= minIndex) {
|
|
109
|
+
this._instancesManager.getArray(this.container).splice(index, deleteCount);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
reset() {
|
|
113
|
+
}
|
|
114
|
+
}
|
package/esm/EmittersPlugin.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { executeOnSingleOrMultiple, isArray,
|
|
1
|
+
import { executeOnSingleOrMultiple, isArray, } from "@tsparticles/engine";
|
|
2
2
|
import { Emitter } from "./Options/Classes/Emitter.js";
|
|
3
|
-
import { EmitterClickMode } from "./Enums/EmitterClickMode.js";
|
|
4
|
-
import { Emitters } from "./Emitters.js";
|
|
5
3
|
export class EmittersPlugin {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
id = "emitters";
|
|
5
|
+
_instancesManager;
|
|
6
|
+
constructor(instancesManager) {
|
|
7
|
+
this._instancesManager = instancesManager;
|
|
9
8
|
}
|
|
10
|
-
getPlugin(container) {
|
|
11
|
-
|
|
9
|
+
async getPlugin(container) {
|
|
10
|
+
const { EmittersPluginInstance } = await import("./EmittersPluginInstance.js");
|
|
11
|
+
return new EmittersPluginInstance(this._instancesManager, container);
|
|
12
12
|
}
|
|
13
|
-
loadOptions(options, source) {
|
|
13
|
+
loadOptions(_container, options, source) {
|
|
14
14
|
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
@@ -21,58 +21,12 @@ export class EmittersPlugin {
|
|
|
21
21
|
return tmp;
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
-
const interactivityEmitters = source?.interactivity?.modes?.emitters;
|
|
25
|
-
if (interactivityEmitters) {
|
|
26
|
-
if (isArray(interactivityEmitters)) {
|
|
27
|
-
options.interactivity.modes.emitters = {
|
|
28
|
-
random: {
|
|
29
|
-
count: 1,
|
|
30
|
-
enable: true,
|
|
31
|
-
},
|
|
32
|
-
value: interactivityEmitters.map(s => {
|
|
33
|
-
const tmp = new Emitter();
|
|
34
|
-
tmp.load(s);
|
|
35
|
-
return tmp;
|
|
36
|
-
}),
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
const emitterMode = interactivityEmitters;
|
|
41
|
-
if (isArray(emitterMode.value)) {
|
|
42
|
-
options.interactivity.modes.emitters = {
|
|
43
|
-
random: {
|
|
44
|
-
count: emitterMode.random.count,
|
|
45
|
-
enable: emitterMode.random.enable,
|
|
46
|
-
},
|
|
47
|
-
value: emitterMode.value.map(s => {
|
|
48
|
-
const tmp = new Emitter();
|
|
49
|
-
tmp.load(s);
|
|
50
|
-
return tmp;
|
|
51
|
-
}),
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
const tmp = new Emitter();
|
|
56
|
-
tmp.load(emitterMode.value);
|
|
57
|
-
options.interactivity.modes.emitters = {
|
|
58
|
-
random: {
|
|
59
|
-
count: emitterMode.random.count,
|
|
60
|
-
enable: emitterMode.random.enable,
|
|
61
|
-
},
|
|
62
|
-
value: tmp,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
24
|
}
|
|
68
25
|
needsPlugin(options) {
|
|
69
26
|
if (!options) {
|
|
70
27
|
return false;
|
|
71
28
|
}
|
|
72
29
|
const emitters = options.emitters;
|
|
73
|
-
return (
|
|
74
|
-
emitters !== undefined ||
|
|
75
|
-
(!!options.interactivity?.events?.onClick?.mode &&
|
|
76
|
-
isInArray(EmitterClickMode.emitter, options.interactivity.events.onClick.mode)));
|
|
30
|
+
return (isArray(emitters) && !!emitters.length) || emitters !== undefined;
|
|
77
31
|
}
|
|
78
32
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { isArray } from "@tsparticles/engine";
|
|
2
|
+
export class EmittersPluginInstance {
|
|
3
|
+
container;
|
|
4
|
+
_instancesManager;
|
|
5
|
+
constructor(instancesManager, container) {
|
|
6
|
+
this.container = container;
|
|
7
|
+
this._instancesManager = instancesManager;
|
|
8
|
+
this._instancesManager.initContainer(container);
|
|
9
|
+
}
|
|
10
|
+
async init() {
|
|
11
|
+
const emittersOptions = this.container.actualOptions.emitters;
|
|
12
|
+
if (isArray(emittersOptions)) {
|
|
13
|
+
for (const emitterOptions of emittersOptions) {
|
|
14
|
+
await this._instancesManager.addEmitter(this.container, emitterOptions);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
await this._instancesManager.addEmitter(this.container, emittersOptions);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
pause() {
|
|
22
|
+
for (const emitter of this._instancesManager.getArray(this.container)) {
|
|
23
|
+
emitter.pause();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
play() {
|
|
27
|
+
for (const emitter of this._instancesManager.getArray(this.container)) {
|
|
28
|
+
emitter.play();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
resize() {
|
|
32
|
+
for (const emitter of this._instancesManager.getArray(this.container)) {
|
|
33
|
+
emitter.resize();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
stop() {
|
|
37
|
+
this._instancesManager.clear(this.container);
|
|
38
|
+
}
|
|
39
|
+
update(delta) {
|
|
40
|
+
this._instancesManager.getArray(this.container).forEach(emitter => {
|
|
41
|
+
emitter.update(delta);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -4,6 +4,19 @@ import { EmitterRate } from "./EmitterRate.js";
|
|
|
4
4
|
import { EmitterShape } from "./EmitterShape.js";
|
|
5
5
|
import { EmitterSize } from "./EmitterSize.js";
|
|
6
6
|
export class Emitter {
|
|
7
|
+
autoPlay;
|
|
8
|
+
direction;
|
|
9
|
+
domId;
|
|
10
|
+
fill;
|
|
11
|
+
life;
|
|
12
|
+
name;
|
|
13
|
+
particles;
|
|
14
|
+
position;
|
|
15
|
+
rate;
|
|
16
|
+
shape;
|
|
17
|
+
size;
|
|
18
|
+
spawnColor;
|
|
19
|
+
startCount;
|
|
7
20
|
constructor() {
|
|
8
21
|
this.autoPlay = true;
|
|
9
22
|
this.fill = true;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { deepExtend, isNull } from "@tsparticles/engine";
|
|
2
2
|
import { EmitterShapeReplace } from "./EmitterShapeReplace.js";
|
|
3
3
|
export class EmitterShape {
|
|
4
|
+
options;
|
|
5
|
+
replace;
|
|
6
|
+
type;
|
|
4
7
|
constructor() {
|
|
5
8
|
this.options = {};
|
|
6
9
|
this.replace = new EmitterShapeReplace();
|
package/esm/ShapeManager.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
const
|
|
1
|
+
const shapeGenerators = new Map();
|
|
2
2
|
export class ShapeManager {
|
|
3
3
|
addShapeGenerator(name, generator) {
|
|
4
4
|
if (!this.getShapeGenerator(name)) {
|
|
5
|
-
|
|
5
|
+
shapeGenerators.set(name, generator);
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
getShapeGenerator(name) {
|
|
9
|
-
return
|
|
9
|
+
return shapeGenerators.get(name);
|
|
10
10
|
}
|
|
11
11
|
getSupportedShapeGenerators() {
|
|
12
|
-
return
|
|
12
|
+
return shapeGenerators.keys();
|
|
13
13
|
}
|
|
14
14
|
}
|
package/esm/constants.js
ADDED
package/esm/index.js
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
export function loadEmittersPlugin(engine) {
|
|
2
|
-
engine.checkVersion("4.0.0-alpha.
|
|
3
|
-
engine.register(async (e) => {
|
|
4
|
-
const { ShapeManager }
|
|
1
|
+
export async function loadEmittersPlugin(engine) {
|
|
2
|
+
engine.checkVersion("4.0.0-alpha.21");
|
|
3
|
+
await engine.register(async (e) => {
|
|
4
|
+
const [{ ensureInteractivityPluginLoaded }, { ShapeManager }, { EmittersInstancesManager }, { EmittersPlugin },] = await Promise.all([
|
|
5
|
+
import("@tsparticles/plugin-interactivity"),
|
|
6
|
+
import("./ShapeManager.js"),
|
|
7
|
+
import("./EmittersInstancesManager.js"),
|
|
8
|
+
import("./EmittersPlugin.js"),
|
|
9
|
+
]), instancesManager = new EmittersInstancesManager(e);
|
|
10
|
+
ensureInteractivityPluginLoaded(e);
|
|
5
11
|
e.emitterShapeManager ??= new ShapeManager();
|
|
6
12
|
e.addEmitterShapeGenerator ??= (name, generator) => {
|
|
7
13
|
e.emitterShapeManager?.addShapeGenerator(name, generator);
|
|
8
14
|
};
|
|
9
|
-
|
|
10
|
-
e.
|
|
15
|
+
e.addPlugin(new EmittersPlugin(instancesManager));
|
|
16
|
+
e.addInteractor?.("externalEmitters", async (container) => {
|
|
17
|
+
const { EmittersInteractor } = await import("./EmittersInteractor.js");
|
|
18
|
+
return new EmittersInteractor(instancesManager, container);
|
|
19
|
+
});
|
|
11
20
|
});
|
|
12
21
|
}
|
|
22
|
+
export function ensureEmittersPluginLoaded(e) {
|
|
23
|
+
if (!e.addEmitterShapeGenerator) {
|
|
24
|
+
throw new Error("tsParticles Emitters Plugin is not loaded");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
13
27
|
export * from "./EmitterShapeBase.js";
|
|
14
28
|
export * from "./Enums/EmitterClickMode.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsparticles/plugin-emitters",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.21",
|
|
4
4
|
"description": "tsParticles emitters plugin",
|
|
5
5
|
"homepage": "https://particles.js.org",
|
|
6
6
|
"repository": {
|
|
@@ -86,7 +86,8 @@
|
|
|
86
86
|
"./package.json": "./package.json"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@tsparticles/engine": "4.0.0-alpha.
|
|
89
|
+
"@tsparticles/engine": "4.0.0-alpha.21",
|
|
90
|
+
"@tsparticles/plugin-interactivity": "4.0.0-alpha.21"
|
|
90
91
|
},
|
|
91
92
|
"publishConfig": {
|
|
92
93
|
"access": "public"
|