@tsparticles/engine 3.7.1 → 3.8.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.
- package/browser/Core/Canvas.js +37 -27
- package/browser/Core/Container.js +10 -13
- package/browser/Core/Engine.js +15 -11
- package/browser/Core/Particle.js +8 -11
- package/browser/Core/Particles.js +10 -14
- package/browser/Core/Retina.js +1 -1
- package/browser/Core/Utils/Constants.js +10 -16
- package/browser/Core/Utils/EventListeners.js +5 -8
- package/browser/Core/Utils/QuadTree.js +1 -1
- package/browser/Core/Utils/Ranges.js +1 -1
- package/browser/Core/Utils/Vectors.js +10 -15
- package/browser/Options/Classes/ManualParticle.js +3 -3
- package/browser/Utils/CanvasUtils.js +8 -14
- package/browser/Utils/ColorUtils.js +12 -17
- package/browser/Utils/EventDispatcher.js +2 -2
- package/browser/Utils/NumberUtils.js +2 -4
- package/browser/Utils/Utils.js +59 -9
- package/cjs/Core/Canvas.js +38 -28
- package/cjs/Core/Container.js +14 -17
- package/cjs/Core/Engine.js +21 -17
- package/cjs/Core/Particle.js +18 -21
- package/cjs/Core/Particles.js +22 -26
- package/cjs/Core/Retina.js +5 -5
- package/cjs/Core/Utils/Constants.js +12 -17
- package/cjs/Core/Utils/EventListeners.js +8 -11
- package/cjs/Core/Utils/QuadTree.js +4 -4
- package/cjs/Core/Utils/Ranges.js +4 -4
- package/cjs/Core/Utils/Vectors.js +11 -16
- package/cjs/Options/Classes/ManualParticle.js +3 -3
- package/cjs/Utils/CanvasUtils.js +14 -20
- package/cjs/Utils/ColorUtils.js +47 -52
- package/cjs/Utils/EventDispatcher.js +5 -5
- package/cjs/Utils/NumberUtils.js +11 -13
- package/cjs/Utils/Utils.js +61 -10
- package/esm/Core/Canvas.js +37 -27
- package/esm/Core/Container.js +10 -13
- package/esm/Core/Engine.js +15 -11
- package/esm/Core/Particle.js +8 -11
- package/esm/Core/Particles.js +10 -14
- package/esm/Core/Retina.js +1 -1
- package/esm/Core/Utils/Constants.js +10 -16
- package/esm/Core/Utils/EventListeners.js +5 -8
- package/esm/Core/Utils/QuadTree.js +1 -1
- package/esm/Core/Utils/Ranges.js +1 -1
- package/esm/Core/Utils/Vectors.js +10 -15
- package/esm/Options/Classes/ManualParticle.js +3 -3
- package/esm/Utils/CanvasUtils.js +8 -14
- package/esm/Utils/ColorUtils.js +12 -17
- package/esm/Utils/EventDispatcher.js +2 -2
- package/esm/Utils/NumberUtils.js +2 -4
- package/esm/Utils/Utils.js +59 -9
- package/package.json +1 -1
- package/report.html +1 -1
- package/tsparticles.engine.js +20 -20
- package/tsparticles.engine.min.js +1 -1
- package/tsparticles.engine.min.js.LICENSE.txt +1 -1
- package/types/Core/Canvas.d.ts +1 -1
- package/types/Core/Engine.d.ts +5 -4
- package/types/Core/Utils/Constants.d.ts +7 -16
- package/types/Utils/ColorUtils.d.ts +1 -1
- package/types/Utils/Utils.d.ts +2 -2
- package/umd/Core/Canvas.js +39 -29
- package/umd/Core/Container.js +14 -17
- package/umd/Core/Engine.js +21 -17
- package/umd/Core/Particle.js +19 -22
- package/umd/Core/Particles.js +23 -27
- package/umd/Core/Retina.js +6 -6
- package/umd/Core/Utils/Constants.js +11 -17
- package/umd/Core/Utils/EventListeners.js +9 -12
- package/umd/Core/Utils/QuadTree.js +5 -5
- package/umd/Core/Utils/Ranges.js +5 -5
- package/umd/Core/Utils/Vectors.js +11 -16
- package/umd/Options/Classes/ManualParticle.js +4 -4
- package/umd/Utils/CanvasUtils.js +15 -21
- package/umd/Utils/ColorUtils.js +48 -53
- package/umd/Utils/EventDispatcher.js +6 -6
- package/umd/Utils/NumberUtils.js +12 -14
- package/umd/Utils/Utils.js +61 -10
package/browser/Core/Canvas.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { clear, drawParticle, drawParticlePlugin, drawPlugin, paintBase, paintImage } from "../Utils/CanvasUtils.js";
|
|
2
|
-
import {
|
|
2
|
+
import { cloneStyle, getFullScreenStyle, getLogger, safeMutationObserver } from "../Utils/Utils.js";
|
|
3
|
+
import { defaultOpacity, defaultTransformValue, generatedAttribute, inverseFactorNumerator, minimumLength, minimumSize, zIndexFactorOffset, } from "./Utils/Constants.js";
|
|
3
4
|
import { getStyleFromHsl, getStyleFromRgb, rangeColorToHsl, rangeColorToRgb } from "../Utils/ColorUtils.js";
|
|
4
|
-
import { generatedAttribute } from "./Utils/Constants.js";
|
|
5
5
|
function setTransformValue(factor, newFactor, key) {
|
|
6
|
-
const newValue = newFactor[key]
|
|
6
|
+
const newValue = newFactor[key];
|
|
7
7
|
if (newValue !== undefined) {
|
|
8
|
-
factor[key] = (factor[key] ??
|
|
8
|
+
factor[key] = (factor[key] ?? defaultTransformValue) * newValue;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
function setStyle(canvas, style, important = false) {
|
|
@@ -20,9 +20,27 @@ function setStyle(canvas, style, important = false) {
|
|
|
20
20
|
if (!elementStyle) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
+
const keys = new Set();
|
|
24
|
+
for (const key in elementStyle) {
|
|
25
|
+
if (!Object.prototype.hasOwnProperty.call(elementStyle, key)) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
keys.add(elementStyle[key]);
|
|
29
|
+
}
|
|
23
30
|
for (const key in style) {
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
if (!Object.prototype.hasOwnProperty.call(style, key)) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
keys.add(style[key]);
|
|
35
|
+
}
|
|
36
|
+
for (const key of keys) {
|
|
37
|
+
const value = style.getPropertyValue(key);
|
|
38
|
+
if (!value) {
|
|
39
|
+
elementStyle.removeProperty(key);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
elementStyle.setProperty(key, value, important ? "important" : "");
|
|
43
|
+
}
|
|
26
44
|
}
|
|
27
45
|
}
|
|
28
46
|
export class Canvas {
|
|
@@ -111,14 +129,13 @@ export class Canvas {
|
|
|
111
129
|
return;
|
|
112
130
|
}
|
|
113
131
|
if (this._fullScreen) {
|
|
114
|
-
this._originalStyle = deepExtend({}, element.style);
|
|
115
132
|
this._setFullScreenStyle();
|
|
116
133
|
}
|
|
117
134
|
else {
|
|
118
135
|
this._resetOriginalStyle();
|
|
119
136
|
}
|
|
120
137
|
for (const key in options.style) {
|
|
121
|
-
if (!key || !options.style) {
|
|
138
|
+
if (!key || !options.style || !Object.prototype.hasOwnProperty.call(options.style, key)) {
|
|
122
139
|
continue;
|
|
123
140
|
}
|
|
124
141
|
const value = options.style[key];
|
|
@@ -133,7 +150,7 @@ export class Canvas {
|
|
|
133
150
|
if (!trail.enable) {
|
|
134
151
|
return;
|
|
135
152
|
}
|
|
136
|
-
const
|
|
153
|
+
const opacity = inverseFactorNumerator / trail.length;
|
|
137
154
|
if (trailFill.color) {
|
|
138
155
|
const fillColor = rangeColorToRgb(this._engine, trailFill.color);
|
|
139
156
|
if (!fillColor) {
|
|
@@ -189,10 +206,10 @@ export class Canvas {
|
|
|
189
206
|
};
|
|
190
207
|
this._resetOriginalStyle = () => {
|
|
191
208
|
const element = this.element, originalStyle = this._originalStyle;
|
|
192
|
-
if (!
|
|
209
|
+
if (!element || !originalStyle) {
|
|
193
210
|
return;
|
|
194
211
|
}
|
|
195
|
-
setStyle(element, originalStyle);
|
|
212
|
+
setStyle(element, originalStyle, true);
|
|
196
213
|
};
|
|
197
214
|
this._safeMutationObserver = callback => {
|
|
198
215
|
if (!this._mutationObserver) {
|
|
@@ -205,16 +222,7 @@ export class Canvas {
|
|
|
205
222
|
if (!element) {
|
|
206
223
|
return;
|
|
207
224
|
}
|
|
208
|
-
|
|
209
|
-
setStyle(element, {
|
|
210
|
-
position: "fixed",
|
|
211
|
-
"z-index": zIndex,
|
|
212
|
-
zIndex: zIndex,
|
|
213
|
-
top: "0",
|
|
214
|
-
left: "0",
|
|
215
|
-
width: "100%",
|
|
216
|
-
height: "100%",
|
|
217
|
-
}, true);
|
|
225
|
+
setStyle(element, getFullScreenStyle(this.container.actualOptions.fullScreen.zIndex), true);
|
|
218
226
|
};
|
|
219
227
|
this._engine = engine;
|
|
220
228
|
this._standardSize = {
|
|
@@ -237,7 +245,7 @@ export class Canvas {
|
|
|
237
245
|
return this.container.actualOptions.fullScreen.enable;
|
|
238
246
|
}
|
|
239
247
|
clear() {
|
|
240
|
-
const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = this._trailFill
|
|
248
|
+
const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = this._trailFill;
|
|
241
249
|
if (options.backgroundMask.enable) {
|
|
242
250
|
this.paint();
|
|
243
251
|
}
|
|
@@ -260,6 +268,7 @@ export class Canvas {
|
|
|
260
268
|
if (this._generated) {
|
|
261
269
|
const element = this.element;
|
|
262
270
|
element?.remove();
|
|
271
|
+
this.element = undefined;
|
|
263
272
|
}
|
|
264
273
|
else {
|
|
265
274
|
this._resetOriginalStyle();
|
|
@@ -287,7 +296,7 @@ export class Canvas {
|
|
|
287
296
|
if (particle.spawning || particle.destroyed) {
|
|
288
297
|
return;
|
|
289
298
|
}
|
|
290
|
-
const radius = particle.getRadius()
|
|
299
|
+
const radius = particle.getRadius();
|
|
291
300
|
if (radius <= minimumSize) {
|
|
292
301
|
return;
|
|
293
302
|
}
|
|
@@ -303,7 +312,7 @@ export class Canvas {
|
|
|
303
312
|
return;
|
|
304
313
|
}
|
|
305
314
|
this.draw((ctx) => {
|
|
306
|
-
const container = this.container, options = container.actualOptions, zIndexOptions = particle.options.zIndex,
|
|
315
|
+
const container = this.container, options = container.actualOptions, zIndexOptions = particle.options.zIndex, zIndexFactor = zIndexFactorOffset - particle.zIndexFactor, zOpacityFactor = zIndexFactor ** zIndexOptions.opacityRate, opacity = particle.bubble.opacity ?? particle.opacity?.value ?? defaultOpacity, strokeOpacity = particle.strokeOpacity ?? opacity, zOpacity = opacity * zOpacityFactor, zStrokeOpacity = strokeOpacity * zOpacityFactor, transform = {}, colorStyles = {
|
|
307
316
|
fill: fColor ? getStyleFromHsl(fColor, zOpacity) : undefined,
|
|
308
317
|
};
|
|
309
318
|
colorStyles.stroke = sColor ? getStyleFromHsl(sColor, zStrokeOpacity) : colorStyles.fill;
|
|
@@ -413,7 +422,7 @@ export class Canvas {
|
|
|
413
422
|
: this._generated;
|
|
414
423
|
this.element = canvas;
|
|
415
424
|
this.element.ariaHidden = "true";
|
|
416
|
-
this._originalStyle =
|
|
425
|
+
this._originalStyle = cloneStyle(this.element.style);
|
|
417
426
|
const standardSize = this._standardSize;
|
|
418
427
|
standardSize.height = canvas.offsetHeight;
|
|
419
428
|
standardSize.width = canvas.offsetWidth;
|
|
@@ -421,14 +430,15 @@ export class Canvas {
|
|
|
421
430
|
canvas.height = retinaSize.height = standardSize.height * pxRatio;
|
|
422
431
|
canvas.width = retinaSize.width = standardSize.width * pxRatio;
|
|
423
432
|
this._context = this.element.getContext("2d");
|
|
433
|
+
this._safeMutationObserver(obs => obs.disconnect());
|
|
434
|
+
this.container.retina.init();
|
|
435
|
+
this.initBackground();
|
|
424
436
|
this._safeMutationObserver(obs => {
|
|
425
437
|
if (!this.element || !(this.element instanceof Node)) {
|
|
426
438
|
return;
|
|
427
439
|
}
|
|
428
440
|
obs.observe(this.element, { attributes: true });
|
|
429
441
|
});
|
|
430
|
-
this.container.retina.init();
|
|
431
|
-
this.initBackground();
|
|
432
442
|
}
|
|
433
443
|
paint() {
|
|
434
444
|
const options = this.container.actualOptions;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { animate, cancelAnimation, getRangeValue } from "../Utils/NumberUtils.js";
|
|
2
|
-
import { errorPrefix, millisecondsToSeconds } from "./Utils/Constants.js";
|
|
2
|
+
import { clickRadius, defaultFps, defaultFpsLimit, errorPrefix, millisecondsToSeconds, minCoordinate, minFpsLimit, removeDeleteCount, removeMinIndex, touchEndLengthOffset, } from "./Utils/Constants.js";
|
|
3
3
|
import { getLogger, safeIntersectionObserver } from "../Utils/Utils.js";
|
|
4
4
|
import { Canvas } from "./Canvas.js";
|
|
5
5
|
import { EventListeners } from "./Utils/EventListeners.js";
|
|
@@ -11,7 +11,6 @@ import { loadOptions } from "../Utils/OptionsUtils.js";
|
|
|
11
11
|
function guardCheck(container) {
|
|
12
12
|
return container && !container.destroyed;
|
|
13
13
|
}
|
|
14
|
-
const defaultFps = 60;
|
|
15
14
|
function initDelta(value, fpsLimit = defaultFps, smooth = false) {
|
|
16
15
|
return {
|
|
17
16
|
value,
|
|
@@ -139,8 +138,8 @@ export class Container {
|
|
|
139
138
|
const mouseEvent = e, pos = {
|
|
140
139
|
x: mouseEvent.offsetX || mouseEvent.clientX,
|
|
141
140
|
y: mouseEvent.offsetY || mouseEvent.clientY,
|
|
142
|
-
}
|
|
143
|
-
clickOrTouchHandler(e, pos,
|
|
141
|
+
};
|
|
142
|
+
clickOrTouchHandler(e, pos, clickRadius);
|
|
144
143
|
}, touchStartHandler = () => {
|
|
145
144
|
if (!guardCheck(this)) {
|
|
146
145
|
return;
|
|
@@ -157,15 +156,15 @@ export class Container {
|
|
|
157
156
|
return;
|
|
158
157
|
}
|
|
159
158
|
if (touched && !touchMoved) {
|
|
160
|
-
const touchEvent = e
|
|
161
|
-
let lastTouch = touchEvent.touches[touchEvent.touches.length -
|
|
159
|
+
const touchEvent = e;
|
|
160
|
+
let lastTouch = touchEvent.touches[touchEvent.touches.length - touchEndLengthOffset];
|
|
162
161
|
if (!lastTouch) {
|
|
163
|
-
lastTouch = touchEvent.changedTouches[touchEvent.changedTouches.length -
|
|
162
|
+
lastTouch = touchEvent.changedTouches[touchEvent.changedTouches.length - touchEndLengthOffset];
|
|
164
163
|
if (!lastTouch) {
|
|
165
164
|
return;
|
|
166
165
|
}
|
|
167
166
|
}
|
|
168
|
-
const element = this.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined,
|
|
167
|
+
const element = this.canvas.element, canvasRect = element ? element.getBoundingClientRect() : undefined, pos = {
|
|
169
168
|
x: lastTouch.clientX - (canvasRect ? canvasRect.left : minCoordinate),
|
|
170
169
|
y: lastTouch.clientY - (canvasRect ? canvasRect.top : minCoordinate),
|
|
171
170
|
};
|
|
@@ -235,10 +234,9 @@ export class Container {
|
|
|
235
234
|
this._engine.clearPlugins(this);
|
|
236
235
|
this.destroyed = true;
|
|
237
236
|
if (remove) {
|
|
238
|
-
const mainArr = this._engine.items, idx = mainArr.findIndex(t => t === this)
|
|
239
|
-
if (idx >=
|
|
240
|
-
|
|
241
|
-
mainArr.splice(idx, deleteCount);
|
|
237
|
+
const mainArr = this._engine.items, idx = mainArr.findIndex(t => t === this);
|
|
238
|
+
if (idx >= removeMinIndex) {
|
|
239
|
+
mainArr.splice(idx, removeDeleteCount);
|
|
242
240
|
}
|
|
243
241
|
}
|
|
244
242
|
this._engine.dispatchEvent(EventType.containerDestroyed, { container: this });
|
|
@@ -314,7 +312,6 @@ export class Container {
|
|
|
314
312
|
this._duration = getRangeValue(duration) * millisecondsToSeconds;
|
|
315
313
|
this._delay = getRangeValue(delay) * millisecondsToSeconds;
|
|
316
314
|
this._lifeTime = 0;
|
|
317
|
-
const defaultFpsLimit = 120, minFpsLimit = 0;
|
|
318
315
|
this.fpsLimit = fpsLimit > minFpsLimit ? fpsLimit : defaultFpsLimit;
|
|
319
316
|
this._smooth = smooth;
|
|
320
317
|
for (const drawer of this.effectDrawers.values()) {
|
package/browser/Core/Engine.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { errorPrefix, generatedAttribute } from "./Utils/Constants.js";
|
|
1
|
+
import { canvasFirstIndex, canvasTag, errorPrefix, generatedAttribute, generatedFalse, generatedTrue, loadMinIndex, loadRandomFactor, none, one, removeDeleteCount, } from "./Utils/Constants.js";
|
|
2
2
|
import { executeOnSingleOrMultiple, getLogger, itemFromSingleOrMultiple } from "../Utils/Utils.js";
|
|
3
3
|
import { Container } from "./Container.js";
|
|
4
4
|
import { EventDispatcher } from "../Utils/EventDispatcher.js";
|
|
@@ -24,7 +24,7 @@ async function getDataFromUrl(data) {
|
|
|
24
24
|
getLogger().error(`${errorPrefix} ${response.status} while retrieving config file`);
|
|
25
25
|
return data.fallback;
|
|
26
26
|
}
|
|
27
|
-
const
|
|
27
|
+
const getCanvasFromContainer = (domContainer) => {
|
|
28
28
|
let canvasEl;
|
|
29
29
|
if (domContainer instanceof HTMLCanvasElement || domContainer.tagName.toLowerCase() === canvasTag) {
|
|
30
30
|
canvasEl = domContainer;
|
|
@@ -35,8 +35,7 @@ const generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", ge
|
|
|
35
35
|
else {
|
|
36
36
|
const existingCanvases = domContainer.getElementsByTagName(canvasTag);
|
|
37
37
|
if (existingCanvases.length) {
|
|
38
|
-
|
|
39
|
-
canvasEl = existingCanvases[firstIndex];
|
|
38
|
+
canvasEl = existingCanvases[canvasFirstIndex];
|
|
40
39
|
canvasEl.dataset[generatedAttribute] = generatedFalse;
|
|
41
40
|
}
|
|
42
41
|
else {
|
|
@@ -97,7 +96,7 @@ export class Engine {
|
|
|
97
96
|
return this._domArray;
|
|
98
97
|
}
|
|
99
98
|
get version() {
|
|
100
|
-
return "3.
|
|
99
|
+
return "3.8.1";
|
|
101
100
|
}
|
|
102
101
|
async addColorManager(manager, refresh = true) {
|
|
103
102
|
this.colorManagers.set(manager.key, manager);
|
|
@@ -165,6 +164,12 @@ export class Engine {
|
|
|
165
164
|
}
|
|
166
165
|
await this.refresh(refresh);
|
|
167
166
|
}
|
|
167
|
+
checkVersion(pluginVersion) {
|
|
168
|
+
if (this.version === pluginVersion) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
throw new Error(`The tsParticles version is different from the loaded plugins version. Engine version: ${this.version}. Plugin version: ${pluginVersion}`);
|
|
172
|
+
}
|
|
168
173
|
clearPlugins(container) {
|
|
169
174
|
this.updaters.delete(container);
|
|
170
175
|
this.movers.delete(container);
|
|
@@ -230,17 +235,16 @@ export class Engine {
|
|
|
230
235
|
item(index) {
|
|
231
236
|
const { items } = this, item = items[index];
|
|
232
237
|
if (!item || item.destroyed) {
|
|
233
|
-
|
|
234
|
-
items.splice(index, deleteCount);
|
|
238
|
+
items.splice(index, removeDeleteCount);
|
|
235
239
|
return;
|
|
236
240
|
}
|
|
237
241
|
return item;
|
|
238
242
|
}
|
|
239
243
|
async load(params) {
|
|
240
|
-
const
|
|
241
|
-
const currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id),
|
|
242
|
-
if (oldIndex >=
|
|
243
|
-
const old = this.item(oldIndex),
|
|
244
|
+
const id = params.id ?? params.element?.id ?? `tsparticles${Math.floor(getRandom() * loadRandomFactor)}`, { index, url } = params, options = url ? await getDataFromUrl({ fallback: params.options, url, index }) : params.options;
|
|
245
|
+
const currentOptions = itemFromSingleOrMultiple(options, index), { items } = this, oldIndex = items.findIndex(v => v.id.description === id), newItem = new Container(this, id, currentOptions);
|
|
246
|
+
if (oldIndex >= loadMinIndex) {
|
|
247
|
+
const old = this.item(oldIndex), deleteCount = old ? one : none;
|
|
244
248
|
if (old && !old.destroyed) {
|
|
245
249
|
old.destroy(false);
|
|
246
250
|
}
|
package/browser/Core/Particle.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Vector, Vector3d } from "./Utils/Vectors.js";
|
|
2
2
|
import { calcExactPositionOrRandomFromSize, clamp, degToRad, getDistance, getParticleBaseVelocity, getParticleDirectionAngle, getRandom, getRangeValue, randomInRange, setRangeValue, } from "../Utils/NumberUtils.js";
|
|
3
|
+
import { decayOffset, defaultRadius, defaultRetryCount, double, errorPrefix, half, millisecondsToSeconds, minRetries, minZ, none, randomColorValue, rollFactor, squareExp, tryCountIncrement, } from "./Utils/Constants.js";
|
|
3
4
|
import { deepExtend, getPosition, initParticleNumericAnimationValue, isInArray, itemFromSingleOrMultiple, } from "../Utils/Utils.js";
|
|
4
|
-
import { errorPrefix, millisecondsToSeconds } from "./Utils/Constants.js";
|
|
5
5
|
import { getHslFromAnimation, rangeColorToRgb } from "../Utils/ColorUtils.js";
|
|
6
6
|
import { EventType } from "../Enums/Types/EventType.js";
|
|
7
7
|
import { Interactivity } from "../Options/Classes/Interactivity/Interactivity.js";
|
|
@@ -11,7 +11,6 @@ import { ParticleOutType } from "../Enums/Types/ParticleOutType.js";
|
|
|
11
11
|
import { PixelMode } from "../Enums/Modes/PixelMode.js";
|
|
12
12
|
import { alterHsl } from "../Utils/CanvasUtils.js";
|
|
13
13
|
import { loadParticlesOptions } from "../Utils/OptionsUtils.js";
|
|
14
|
-
const defaultRetryCount = 0, double = 2, half = 0.5, squareExp = 2, randomString = "random";
|
|
15
14
|
function loadEffectData(effect, effectOptions, id, reduceDuplicates) {
|
|
16
15
|
const effectData = effectOptions.options[effect];
|
|
17
16
|
if (!effectData) {
|
|
@@ -81,8 +80,7 @@ export class Particle {
|
|
|
81
80
|
fixVertical(outModes.top ?? outModes.default);
|
|
82
81
|
fixVertical(outModes.bottom ?? outModes.default);
|
|
83
82
|
if (this._checkOverlap(pos, tryCount)) {
|
|
84
|
-
|
|
85
|
-
return this._calcPosition(container, undefined, zIndex, tryCount + increment);
|
|
83
|
+
return this._calcPosition(container, undefined, zIndex, tryCount + tryCountIncrement);
|
|
86
84
|
}
|
|
87
85
|
return pos;
|
|
88
86
|
};
|
|
@@ -112,7 +110,7 @@ export class Particle {
|
|
|
112
110
|
if (overlapOptions.enable) {
|
|
113
111
|
return false;
|
|
114
112
|
}
|
|
115
|
-
const retries = overlapOptions.retries
|
|
113
|
+
const retries = overlapOptions.retries;
|
|
116
114
|
if (retries >= minRetries && tryCount > retries) {
|
|
117
115
|
throw new Error(`${errorPrefix} particle is overlapping and can't be placed`);
|
|
118
116
|
}
|
|
@@ -122,7 +120,7 @@ export class Particle {
|
|
|
122
120
|
if (!color || !this.roll || (!this.backColor && !this.roll.alter)) {
|
|
123
121
|
return color;
|
|
124
122
|
}
|
|
125
|
-
const
|
|
123
|
+
const backFactor = this.roll.horizontal && this.roll.vertical ? double * rollFactor : rollFactor, backSum = this.roll.horizontal ? Math.PI * half : none, rolled = Math.floor(((this.roll.angle ?? none) + backSum) / (Math.PI / backFactor)) % double;
|
|
126
124
|
if (!rolled) {
|
|
127
125
|
return color;
|
|
128
126
|
}
|
|
@@ -135,10 +133,10 @@ export class Particle {
|
|
|
135
133
|
return color;
|
|
136
134
|
};
|
|
137
135
|
this._initPosition = position => {
|
|
138
|
-
const container = this.container, zIndexValue = getRangeValue(this.options.zIndex.value)
|
|
136
|
+
const container = this.container, zIndexValue = getRangeValue(this.options.zIndex.value);
|
|
139
137
|
this.position = this._calcPosition(container, position, clamp(zIndexValue, minZ, container.zLayers));
|
|
140
138
|
this.initialPosition = this.position.copy();
|
|
141
|
-
const canvasSize = container.canvas.size
|
|
139
|
+
const canvasSize = container.canvas.size;
|
|
142
140
|
this.moveCenter = {
|
|
143
141
|
...getPosition(this.options.move.center, canvasSize),
|
|
144
142
|
radius: this.options.move.center.radius ?? defaultRadius,
|
|
@@ -246,11 +244,11 @@ export class Particle {
|
|
|
246
244
|
}
|
|
247
245
|
}
|
|
248
246
|
}
|
|
249
|
-
if (this.effect ===
|
|
247
|
+
if (this.effect === randomColorValue) {
|
|
250
248
|
const availableEffects = [...this.container.effectDrawers.keys()];
|
|
251
249
|
this.effect = availableEffects[Math.floor(Math.random() * availableEffects.length)];
|
|
252
250
|
}
|
|
253
|
-
if (this.shape ===
|
|
251
|
+
if (this.shape === randomColorValue) {
|
|
254
252
|
const availableShapes = [...this.container.shapeDrawers.keys()];
|
|
255
253
|
this.shape = availableShapes[Math.floor(Math.random() * availableShapes.length)];
|
|
256
254
|
}
|
|
@@ -294,7 +292,6 @@ export class Particle {
|
|
|
294
292
|
this._initPosition(position);
|
|
295
293
|
this.initialVelocity = this._calculateVelocity();
|
|
296
294
|
this.velocity = this.initialVelocity.copy();
|
|
297
|
-
const decayOffset = 1;
|
|
298
295
|
this.moveDecay = decayOffset - getRangeValue(this.options.move.decay);
|
|
299
296
|
const particles = container.particles;
|
|
300
297
|
particles.setLastZIndex(this.position.z);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { countOffset, defaultDensityFactor, defaultRemoveQuantity, deleteCount, errorPrefix, lengthOffset, manualCount, minCount, minIndex, minLimit, posOffset, qTreeCapacity, sizeFactor, squareExp, } from "./Utils/Constants.js";
|
|
1
2
|
import { getLogger, getPosition } from "../Utils/Utils.js";
|
|
2
3
|
import { EventType } from "../Enums/Types/EventType.js";
|
|
3
4
|
import { InteractionManager } from "./Utils/InteractionManager.js";
|
|
@@ -6,10 +7,8 @@ import { Particle } from "./Particle.js";
|
|
|
6
7
|
import { Point } from "./Utils/Point.js";
|
|
7
8
|
import { QuadTree } from "./Utils/QuadTree.js";
|
|
8
9
|
import { Rectangle } from "./Utils/Ranges.js";
|
|
9
|
-
import { errorPrefix } from "./Utils/Constants.js";
|
|
10
|
-
const qTreeCapacity = 4, squareExp = 2, defaultRemoveQuantity = 1;
|
|
11
10
|
const qTreeRectangle = (canvasSize) => {
|
|
12
|
-
const { height, width } = canvasSize
|
|
11
|
+
const { height, width } = canvasSize;
|
|
13
12
|
return new Rectangle(posOffset * width, posOffset * height, sizeFactor * width, sizeFactor * height);
|
|
14
13
|
};
|
|
15
14
|
export class Particles {
|
|
@@ -28,7 +27,7 @@ export class Particles {
|
|
|
28
27
|
}
|
|
29
28
|
return;
|
|
30
29
|
}
|
|
31
|
-
const densityFactor = this._initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value,
|
|
30
|
+
const densityFactor = this._initDensityFactor(numberOptions.density), optParticlesNumber = numberOptions.value, optParticlesLimit = numberOptions.limit.value > minLimit ? numberOptions.limit.value : optParticlesNumber, particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor + manualCount, particlesCount = Math.min(this.count, this.filter(t => t.group === group).length);
|
|
32
31
|
if (group === undefined) {
|
|
33
32
|
this._limit = numberOptions.limit.value * densityFactor;
|
|
34
33
|
}
|
|
@@ -43,9 +42,9 @@ export class Particles {
|
|
|
43
42
|
}
|
|
44
43
|
};
|
|
45
44
|
this._initDensityFactor = densityOptions => {
|
|
46
|
-
const container = this._container
|
|
45
|
+
const container = this._container;
|
|
47
46
|
if (!container.canvas.element || !densityOptions.enable) {
|
|
48
|
-
return
|
|
47
|
+
return defaultDensityFactor;
|
|
49
48
|
}
|
|
50
49
|
const canvas = container.canvas.element, pxRatio = container.retina.pixelRatio;
|
|
51
50
|
return (canvas.width * canvas.height) / (densityOptions.height * densityOptions.width * pxRatio ** squareExp);
|
|
@@ -84,7 +83,7 @@ export class Particles {
|
|
|
84
83
|
if (!particle || particle.group !== group) {
|
|
85
84
|
return false;
|
|
86
85
|
}
|
|
87
|
-
const zIdx = this._zArray.indexOf(particle)
|
|
86
|
+
const zIdx = this._zArray.indexOf(particle);
|
|
88
87
|
this._array.splice(index, deleteCount);
|
|
89
88
|
this._zArray.splice(zIdx, deleteCount);
|
|
90
89
|
particle.destroy(override);
|
|
@@ -122,11 +121,11 @@ export class Particles {
|
|
|
122
121
|
options.manualParticles.forEach(p => this.addParticle(p.position ? getPosition(p.position, container.canvas.size) : undefined, p.options));
|
|
123
122
|
}
|
|
124
123
|
addParticle(position, overrideOptions, group, initializer) {
|
|
125
|
-
const limitMode = this._container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this._limit : (this._groupLimits.get(group) ?? this._limit), currentCount = this.count
|
|
124
|
+
const limitMode = this._container.actualOptions.particles.number.limit.mode, limit = group === undefined ? this._limit : (this._groupLimits.get(group) ?? this._limit), currentCount = this.count;
|
|
126
125
|
if (limit > minLimit) {
|
|
127
126
|
switch (limitMode) {
|
|
128
127
|
case LimitMode.delete: {
|
|
129
|
-
const
|
|
128
|
+
const countToRemove = currentCount + countOffset - limit;
|
|
130
129
|
if (countToRemove > minCount) {
|
|
131
130
|
this.removeQuantity(countToRemove);
|
|
132
131
|
}
|
|
@@ -227,7 +226,6 @@ export class Particles {
|
|
|
227
226
|
this.removeAt(this._array.indexOf(particle), undefined, group, override);
|
|
228
227
|
}
|
|
229
228
|
removeAt(index, quantity = defaultRemoveQuantity, group, override) {
|
|
230
|
-
const minIndex = 0;
|
|
231
229
|
if (index < minIndex || index > this.count) {
|
|
232
230
|
return;
|
|
233
231
|
}
|
|
@@ -240,11 +238,10 @@ export class Particles {
|
|
|
240
238
|
}
|
|
241
239
|
}
|
|
242
240
|
removeQuantity(quantity, group) {
|
|
243
|
-
|
|
244
|
-
this.removeAt(defaultIndex, quantity, group);
|
|
241
|
+
this.removeAt(minIndex, quantity, group);
|
|
245
242
|
}
|
|
246
243
|
setDensity() {
|
|
247
|
-
const options = this._container.actualOptions, groups = options.particles.groups
|
|
244
|
+
const options = this._container.actualOptions, groups = options.particles.groups;
|
|
248
245
|
for (const group in groups) {
|
|
249
246
|
this._applyDensity(groups[group], manualCount, group);
|
|
250
247
|
}
|
|
@@ -320,7 +317,6 @@ export class Particles {
|
|
|
320
317
|
if (this._needsSort) {
|
|
321
318
|
const zArray = this._zArray;
|
|
322
319
|
zArray.sort((a, b) => b.position.z - a.position.z || a.id - b.id);
|
|
323
|
-
const lengthOffset = 1;
|
|
324
320
|
this._lastZIndex = zArray[zArray.length - lengthOffset].position.z;
|
|
325
321
|
this._needsSort = false;
|
|
326
322
|
}
|
package/browser/Core/Retina.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { defaultRatio, defaultReduceFactor } from "./Utils/Constants.js";
|
|
1
2
|
import { getRangeValue } from "../Utils/NumberUtils.js";
|
|
2
3
|
import { isSsr } from "../Utils/Utils.js";
|
|
3
|
-
const defaultRatio = 1, defaultReduceFactor = 1;
|
|
4
4
|
export class Retina {
|
|
5
5
|
constructor(container) {
|
|
6
6
|
this.container = container;
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
export const generatedAttribute = "generated"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export const resizeEvent = "resize";
|
|
12
|
-
export const visibilityChangeEvent = "visibilitychange";
|
|
13
|
-
export const errorPrefix = "tsParticles - Error";
|
|
14
|
-
export const percentDenominator = 100;
|
|
15
|
-
export const halfRandom = 0.5;
|
|
16
|
-
export const millisecondsToSeconds = 1000;
|
|
1
|
+
export const generatedAttribute = "generated", mouseDownEvent = "pointerdown", mouseUpEvent = "pointerup", mouseLeaveEvent = "pointerleave", mouseOutEvent = "pointerout", mouseMoveEvent = "pointermove", touchStartEvent = "touchstart", touchEndEvent = "touchend", touchMoveEvent = "touchmove", touchCancelEvent = "touchcancel", resizeEvent = "resize", visibilityChangeEvent = "visibilitychange", errorPrefix = "tsParticles - Error", percentDenominator = 100, half = 0.5, millisecondsToSeconds = 1000, originPoint = {
|
|
2
|
+
x: 0,
|
|
3
|
+
y: 0,
|
|
4
|
+
z: 0,
|
|
5
|
+
}, defaultTransform = {
|
|
6
|
+
a: 1,
|
|
7
|
+
b: 0,
|
|
8
|
+
c: 0,
|
|
9
|
+
d: 1,
|
|
10
|
+
}, randomColorValue = "random", midColorValue = "mid", double = 2, doublePI = Math.PI * double, defaultFps = 60, defaultAlpha = 1, generatedTrue = "true", generatedFalse = "false", canvasTag = "canvas", defaultRetryCount = 0, squareExp = 2, qTreeCapacity = 4, defaultRemoveQuantity = 1, defaultRatio = 1, defaultReduceFactor = 1, subdivideCount = 4, inverseFactorNumerator = 1.0, rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, empty = 0, quarter = 0.25, threeQuarter = half + quarter, minVelocity = 0, defaultTransformValue = 1, minimumSize = 0, minimumLength = 0, zIndexFactorOffset = 1, defaultOpacity = 1, clickRadius = 1, touchEndLengthOffset = 1, minCoordinate = 0, removeDeleteCount = 1, removeMinIndex = 0, defaultFpsLimit = 120, minFpsLimit = 0, canvasFirstIndex = 0, loadRandomFactor = 10000, loadMinIndex = 0, one = 1, none = 0, decayOffset = 1, tryCountIncrement = 1, minRetries = 0, rollFactor = 1, minZ = 0, defaultRadius = 0, posOffset = -quarter, sizeFactor = 1.5, minLimit = 0, countOffset = 1, minCount = 0, minIndex = 0, manualCount = 0, lengthOffset = 1, defaultDensityFactor = 1, deleteCount = 1, touchDelay = 500, manualDefaultPosition = 50, defaultAngle = 0, identity = 1, minStrokeWidth = 0, lFactor = 1, lMin = 0, rgbFactor = 255, triple = 3, sextuple = 6, sNormalizedOffset = 1, phaseNumerator = 1, defaultRgbMin = 0, defaultVelocity = 0, defaultLoops = 0, defaultTime = 0;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { double, lengthOffset, millisecondsToSeconds, minCoordinate, mouseDownEvent, mouseLeaveEvent, mouseMoveEvent, mouseOutEvent, mouseUpEvent, resizeEvent, touchCancelEvent, touchDelay, touchEndEvent, touchMoveEvent, touchStartEvent, visibilityChangeEvent, } from "./Constants.js";
|
|
1
2
|
import { executeOnSingleOrMultiple, safeMatchMedia } from "../../Utils/Utils.js";
|
|
2
|
-
import { millisecondsToSeconds, mouseDownEvent, mouseLeaveEvent, mouseMoveEvent, mouseOutEvent, mouseUpEvent, resizeEvent, touchCancelEvent, touchEndEvent, touchMoveEvent, touchStartEvent, visibilityChangeEvent, } from "./Constants.js";
|
|
3
3
|
import { InteractivityDetect } from "../../Enums/InteractivityDetect.js";
|
|
4
4
|
import { isBoolean } from "../../Utils/TypeUtils.js";
|
|
5
|
-
const double = 2;
|
|
6
5
|
function manageListener(element, event, handler, add, options) {
|
|
7
6
|
if (add) {
|
|
8
7
|
let addOptions = { passive: true };
|
|
@@ -35,7 +34,6 @@ export class EventListeners {
|
|
|
35
34
|
executeOnSingleOrMultiple(onClick.mode, mode => this.container.handleClickMode(mode));
|
|
36
35
|
}
|
|
37
36
|
if (e.type === "touchend") {
|
|
38
|
-
const touchDelay = 500;
|
|
39
37
|
setTimeout(() => this._mouseTouchFinish(), touchDelay);
|
|
40
38
|
}
|
|
41
39
|
};
|
|
@@ -77,8 +75,7 @@ export class EventListeners {
|
|
|
77
75
|
this._resizeTimeout = setTimeout(() => void handleResize(), this.container.actualOptions.interactivity.events.resize.delay * millisecondsToSeconds);
|
|
78
76
|
};
|
|
79
77
|
this._manageInteractivityListeners = (mouseLeaveTmpEvent, add) => {
|
|
80
|
-
const handlers = this._handlers, container = this.container, options = container.actualOptions;
|
|
81
|
-
const interactivityEl = container.interactivity.element;
|
|
78
|
+
const handlers = this._handlers, container = this.container, options = container.actualOptions, interactivityEl = container.interactivity.element;
|
|
82
79
|
if (!interactivityEl) {
|
|
83
80
|
return;
|
|
84
81
|
}
|
|
@@ -259,10 +256,10 @@ export class EventListeners {
|
|
|
259
256
|
else {
|
|
260
257
|
this._canPush = e.type !== "touchmove";
|
|
261
258
|
if (canvasEl) {
|
|
262
|
-
const touchEvent = e,
|
|
259
|
+
const touchEvent = e, lastTouch = touchEvent.touches[touchEvent.touches.length - lengthOffset], canvasRect = canvasEl.getBoundingClientRect();
|
|
263
260
|
pos = {
|
|
264
|
-
x: lastTouch.clientX - (canvasRect.left ??
|
|
265
|
-
y: lastTouch.clientY - (canvasRect.top ??
|
|
261
|
+
x: lastTouch.clientX - (canvasRect.left ?? minCoordinate),
|
|
262
|
+
y: lastTouch.clientY - (canvasRect.top ?? minCoordinate),
|
|
266
263
|
};
|
|
267
264
|
}
|
|
268
265
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Circle, Rectangle } from "./Ranges.js";
|
|
2
|
+
import { double, half, subdivideCount } from "./Constants.js";
|
|
2
3
|
import { getDistance } from "../../Utils/NumberUtils.js";
|
|
3
|
-
const half = 0.5, double = 2, subdivideCount = 4;
|
|
4
4
|
export class QuadTree {
|
|
5
5
|
constructor(rectangle, capacity) {
|
|
6
6
|
this.rectangle = rectangle;
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import { errorPrefix } from "./Constants.js";
|
|
1
|
+
import { errorPrefix, inverseFactorNumerator, none, originPoint, squareExp } from "./Constants.js";
|
|
2
2
|
import { isNumber } from "../../Utils/TypeUtils.js";
|
|
3
|
-
const origin = {
|
|
4
|
-
x: 0,
|
|
5
|
-
y: 0,
|
|
6
|
-
z: 0,
|
|
7
|
-
}, squareExp = 2, inverseFactorNumerator = 1.0;
|
|
8
3
|
export class Vector3d {
|
|
9
4
|
constructor(xOrCoords, y, z) {
|
|
10
5
|
this._updateFromAngle = (angle, length) => {
|
|
@@ -15,19 +10,19 @@ export class Vector3d {
|
|
|
15
10
|
this.x = xOrCoords.x;
|
|
16
11
|
this.y = xOrCoords.y;
|
|
17
12
|
const coords3d = xOrCoords;
|
|
18
|
-
this.z = coords3d.z ? coords3d.z :
|
|
13
|
+
this.z = coords3d.z ? coords3d.z : originPoint.z;
|
|
19
14
|
}
|
|
20
15
|
else if (xOrCoords !== undefined && y !== undefined) {
|
|
21
16
|
this.x = xOrCoords;
|
|
22
17
|
this.y = y;
|
|
23
|
-
this.z = z ??
|
|
18
|
+
this.z = z ?? originPoint.z;
|
|
24
19
|
}
|
|
25
20
|
else {
|
|
26
21
|
throw new Error(`${errorPrefix} Vector3d not initialized correctly`);
|
|
27
22
|
}
|
|
28
23
|
}
|
|
29
24
|
static get origin() {
|
|
30
|
-
return Vector3d.create(
|
|
25
|
+
return Vector3d.create(originPoint.x, originPoint.y, originPoint.z);
|
|
31
26
|
}
|
|
32
27
|
get angle() {
|
|
33
28
|
return Math.atan2(this.y, this.x);
|
|
@@ -84,19 +79,19 @@ export class Vector3d {
|
|
|
84
79
|
this.z *= n;
|
|
85
80
|
}
|
|
86
81
|
normalize() {
|
|
87
|
-
const length = this.length
|
|
88
|
-
if (length !=
|
|
82
|
+
const length = this.length;
|
|
83
|
+
if (length != none) {
|
|
89
84
|
this.multTo(inverseFactorNumerator / length);
|
|
90
85
|
}
|
|
91
86
|
}
|
|
92
87
|
rotate(angle) {
|
|
93
|
-
return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle),
|
|
88
|
+
return Vector3d.create(this.x * Math.cos(angle) - this.y * Math.sin(angle), this.x * Math.sin(angle) + this.y * Math.cos(angle), originPoint.z);
|
|
94
89
|
}
|
|
95
90
|
setTo(c) {
|
|
96
91
|
this.x = c.x;
|
|
97
92
|
this.y = c.y;
|
|
98
93
|
const v3d = c;
|
|
99
|
-
this.z = v3d.z ? v3d.z :
|
|
94
|
+
this.z = v3d.z ? v3d.z : originPoint.z;
|
|
100
95
|
}
|
|
101
96
|
sub(v) {
|
|
102
97
|
return Vector3d.create(this.x - v.x, this.y - v.y, this.z - v.z);
|
|
@@ -109,10 +104,10 @@ export class Vector3d {
|
|
|
109
104
|
}
|
|
110
105
|
export class Vector extends Vector3d {
|
|
111
106
|
constructor(xOrCoords, y) {
|
|
112
|
-
super(xOrCoords, y,
|
|
107
|
+
super(xOrCoords, y, originPoint.z);
|
|
113
108
|
}
|
|
114
109
|
static get origin() {
|
|
115
|
-
return Vector.create(
|
|
110
|
+
return Vector.create(originPoint.x, originPoint.y);
|
|
116
111
|
}
|
|
117
112
|
static clone(source) {
|
|
118
113
|
return Vector.create(source.x, source.y);
|