tsparticles 1.37.3 → 1.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Core/Canvas.d.ts +2 -2
- package/Core/Canvas.js +17 -7
- package/Core/Loader.js +4 -9
- package/Options/Classes/Options.d.ts +1 -0
- package/Options/Classes/Options.js +2 -0
- package/Options/Interfaces/IOptions.d.ts +1 -0
- package/README.md +68 -0
- package/Utils/Constants.d.ts +1 -1
- package/Utils/Constants.js +1 -1
- package/Utils/EventListeners.d.ts +1 -0
- package/Utils/EventListeners.js +14 -3
- package/Utils/Utils.js +4 -7
- package/browser/Core/Canvas.d.ts +2 -2
- package/browser/Core/Canvas.js +17 -7
- package/browser/Core/Loader.js +4 -9
- package/browser/Options/Classes/Options.d.ts +1 -0
- package/browser/Options/Classes/Options.js +3 -1
- package/browser/Options/Interfaces/IOptions.d.ts +1 -0
- package/browser/Utils/Constants.d.ts +1 -4
- package/browser/Utils/Constants.js +1 -4
- package/browser/Utils/EventListeners.d.ts +1 -0
- package/browser/Utils/EventListeners.js +15 -4
- package/browser/Utils/Utils.js +5 -8
- package/esm/Core/Canvas.d.ts +2 -2
- package/esm/Core/Canvas.js +17 -7
- package/esm/Core/Loader.js +4 -9
- package/esm/Options/Classes/Options.d.ts +1 -0
- package/esm/Options/Classes/Options.js +3 -1
- package/esm/Options/Interfaces/IOptions.d.ts +1 -0
- package/esm/Utils/Constants.d.ts +1 -1
- package/esm/Utils/Constants.js +1 -1
- package/esm/Utils/EventListeners.d.ts +1 -0
- package/esm/Utils/EventListeners.js +15 -4
- package/esm/Utils/Utils.js +5 -8
- package/package.json +1 -1
- package/report.html +2 -2
- package/report.slim.html +2 -2
- package/scripts/install.js +14 -3
- package/tsparticles.js +38 -28
- package/tsparticles.min.js +2 -2
- package/tsparticles.slim.js +38 -28
- package/tsparticles.slim.min.js +2 -2
package/Core/Canvas.d.ts
CHANGED
|
@@ -13,11 +13,11 @@ export declare class Canvas {
|
|
|
13
13
|
private originalStyle?;
|
|
14
14
|
constructor(container: Container);
|
|
15
15
|
init(): void;
|
|
16
|
-
loadCanvas(canvas: HTMLCanvasElement
|
|
16
|
+
loadCanvas(canvas: HTMLCanvasElement): void;
|
|
17
17
|
destroy(): void;
|
|
18
18
|
paint(): void;
|
|
19
19
|
clear(): void;
|
|
20
|
-
windowResize(): void
|
|
20
|
+
windowResize(): Promise<void>;
|
|
21
21
|
resize(): void;
|
|
22
22
|
drawConnectLine(p1: IParticle, p2: IParticle): void;
|
|
23
23
|
drawGrabLine(particle: IParticle, lineColor: IRgb, opacity: number, mousePos: ICoordinates): void;
|
package/Core/Canvas.js
CHANGED
|
@@ -21,15 +21,15 @@ class Canvas {
|
|
|
21
21
|
this.initBackground();
|
|
22
22
|
this.paint();
|
|
23
23
|
}
|
|
24
|
-
loadCanvas(canvas
|
|
24
|
+
loadCanvas(canvas) {
|
|
25
25
|
var _a;
|
|
26
|
-
if (!canvas.className) {
|
|
27
|
-
canvas.className = Utils_1.Constants.canvasClass;
|
|
28
|
-
}
|
|
29
26
|
if (this.generatedCanvas) {
|
|
30
27
|
(_a = this.element) === null || _a === void 0 ? void 0 : _a.remove();
|
|
31
28
|
}
|
|
32
|
-
this.generatedCanvas =
|
|
29
|
+
this.generatedCanvas =
|
|
30
|
+
canvas.dataset && Utils_1.Constants.generatedAttribute in canvas.dataset
|
|
31
|
+
? canvas.dataset[Utils_1.Constants.generatedAttribute] === "true"
|
|
32
|
+
: this.generatedCanvas;
|
|
33
33
|
this.element = canvas;
|
|
34
34
|
this.originalStyle = (0, Utils_1.deepExtend)({}, this.element.style);
|
|
35
35
|
this.size.height = canvas.offsetHeight;
|
|
@@ -74,7 +74,7 @@ class Canvas {
|
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
windowResize() {
|
|
77
|
+
async windowResize() {
|
|
78
78
|
if (!this.element) {
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
@@ -88,7 +88,7 @@ class Canvas {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
if (needsRefresh) {
|
|
91
|
-
container.refresh();
|
|
91
|
+
await container.refresh();
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
resize() {
|
|
@@ -291,6 +291,16 @@ class Canvas {
|
|
|
291
291
|
element.style.width = originalStyle.width;
|
|
292
292
|
element.style.height = originalStyle.height;
|
|
293
293
|
}
|
|
294
|
+
for (const key in options.style) {
|
|
295
|
+
if (!key || !options.style) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
const value = options.style[key];
|
|
299
|
+
if (!value) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
element.style[key] = value;
|
|
303
|
+
}
|
|
294
304
|
}
|
|
295
305
|
paintBase(baseColor) {
|
|
296
306
|
this.draw((ctx) => {
|
package/Core/Loader.js
CHANGED
|
@@ -41,24 +41,19 @@ class Loader {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
let canvasEl;
|
|
44
|
-
let generatedCanvas;
|
|
45
44
|
if (domContainer.tagName.toLowerCase() === "canvas") {
|
|
46
45
|
canvasEl = domContainer;
|
|
47
|
-
|
|
46
|
+
canvasEl.dataset[Utils_1.Constants.generatedAttribute] = "false";
|
|
48
47
|
}
|
|
49
48
|
else {
|
|
50
49
|
const existingCanvases = domContainer.getElementsByTagName("canvas");
|
|
51
50
|
if (existingCanvases.length) {
|
|
52
51
|
canvasEl = existingCanvases[0];
|
|
53
|
-
|
|
54
|
-
canvasEl.className = Utils_1.Constants.canvasClass;
|
|
55
|
-
}
|
|
56
|
-
generatedCanvas = false;
|
|
52
|
+
canvasEl.dataset[Utils_1.Constants.generatedAttribute] = "false";
|
|
57
53
|
}
|
|
58
54
|
else {
|
|
59
|
-
generatedCanvas = true;
|
|
60
55
|
canvasEl = document.createElement("canvas");
|
|
61
|
-
canvasEl.
|
|
56
|
+
canvasEl.dataset[Utils_1.Constants.generatedAttribute] = "true";
|
|
62
57
|
canvasEl.style.width = "100%";
|
|
63
58
|
canvasEl.style.height = "100%";
|
|
64
59
|
domContainer.appendChild(canvasEl);
|
|
@@ -71,7 +66,7 @@ class Loader {
|
|
|
71
66
|
else {
|
|
72
67
|
dom.push(newItem);
|
|
73
68
|
}
|
|
74
|
-
newItem.canvas.loadCanvas(canvasEl
|
|
69
|
+
newItem.canvas.loadCanvas(canvasEl);
|
|
75
70
|
await newItem.start();
|
|
76
71
|
return newItem;
|
|
77
72
|
}
|
|
@@ -32,6 +32,7 @@ export declare class Options implements IOptions, IOptionLoader<IOptions> {
|
|
|
32
32
|
pauseOnBlur: boolean;
|
|
33
33
|
pauseOnOutsideViewport: boolean;
|
|
34
34
|
preset?: string | string[];
|
|
35
|
+
style: RecursivePartial<CSSStyleDeclaration>;
|
|
35
36
|
responsive: Responsive[];
|
|
36
37
|
themes: Theme[];
|
|
37
38
|
zLayers: number;
|
|
@@ -35,6 +35,7 @@ class Options {
|
|
|
35
35
|
this.pauseOnBlur = true;
|
|
36
36
|
this.pauseOnOutsideViewport = true;
|
|
37
37
|
this.responsive = [];
|
|
38
|
+
this.style = {};
|
|
38
39
|
this.themes = [];
|
|
39
40
|
this.zLayers = 100;
|
|
40
41
|
}
|
|
@@ -113,6 +114,7 @@ class Options {
|
|
|
113
114
|
}
|
|
114
115
|
this.motion.load(data.motion);
|
|
115
116
|
this.particles.load(data.particles);
|
|
117
|
+
this.style = (0, Utils_1.deepExtend)(this.style, data.style);
|
|
116
118
|
Utils_1.Plugins.loadOptions(this, data);
|
|
117
119
|
if (data.responsive !== undefined) {
|
|
118
120
|
for (const responsive of data.responsive) {
|
package/README.md
CHANGED
|
@@ -13,6 +13,36 @@ React.js, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Inferno, Riot.j
|
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
+
## Table of Contents
|
|
17
|
+
|
|
18
|
+
- [Use for your website](#Do-you-want-to-use-it-on-your-website)
|
|
19
|
+
- [Library installation](#Library-installation)
|
|
20
|
+
- [Official components for some of the most used frameworks](#Official-components-for-some-of-the-most-used-frameworks)
|
|
21
|
+
- [Angular](#Angular)
|
|
22
|
+
- [Inferno](#Inferno)
|
|
23
|
+
- [jQuery](#jQuery)
|
|
24
|
+
- [Preact](#Preact)
|
|
25
|
+
- [ReactJS](#ReactJS)
|
|
26
|
+
- [RiotJS](#RiotJS)
|
|
27
|
+
- [SolidJS](#SolidJS)
|
|
28
|
+
- [Svelte](#Svelte)
|
|
29
|
+
- [VueJS 2.x](#VueJS-2x)
|
|
30
|
+
- [VueJS 3.x](#VueJS-3x)
|
|
31
|
+
- [Web Components](#Web-Components)
|
|
32
|
+
- [WordPress](#WordPress)
|
|
33
|
+
- [Templates and Resources](#Templates-and-Resources)
|
|
34
|
+
- [Demo / Generator](#Demo--Generator)
|
|
35
|
+
- [Characters as particles](#Characters-as-particles)
|
|
36
|
+
- [Mouse hover connections](#Mouse-hover-connections)
|
|
37
|
+
- [Polygon mask](#Polygon-mask)
|
|
38
|
+
- [Animated stars](#Animated-stars)
|
|
39
|
+
- [Nyan cat flying on scrolling stars](#Nyan-cat-flying-on-scrolling-stars)
|
|
40
|
+
- [Background Mask particles](#Background-Mask-particles)
|
|
41
|
+
- [Migrating from Particles.js](#Migrating-from-Particlesjs)
|
|
42
|
+
- [Plugins/Customizations](#PluginsCustomizations)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
16
46
|
## Do you want to use it on your website?
|
|
17
47
|
|
|
18
48
|
_Documentation and Development references [here](https://particles.js.org/docs/) 📖_
|
|
@@ -221,6 +251,22 @@ You can find the instructions [here](https://github.com/matteobruni/tsparticles/
|
|
|
221
251
|
|
|
222
252
|
You can find the instructions [here](https://github.com/matteobruni/tsparticles/blob/main/components/react/README.md)
|
|
223
253
|
|
|
254
|
+
### RiotJS
|
|
255
|
+
|
|
256
|
+
#### `riot-particles`
|
|
257
|
+
|
|
258
|
+
[](https://www.npmjs.com/package/riot-particles) [](https://www.npmjs.com/package/riot-particles)
|
|
259
|
+
|
|
260
|
+
You can find the instructions [here](https://github.com/matteobruni/tsparticles/blob/main/components/riot/README.md)
|
|
261
|
+
|
|
262
|
+
### SolidJS
|
|
263
|
+
|
|
264
|
+
#### `solid-particles`
|
|
265
|
+
|
|
266
|
+
[](https://www.npmjs.com/package/solid-particles) [](https://www.npmjs.com/package/solid-particles)
|
|
267
|
+
|
|
268
|
+
You can find the instructions [here](https://github.com/matteobruni/tsparticles/blob/main/components/solid/README.md)
|
|
269
|
+
|
|
224
270
|
### Svelte
|
|
225
271
|
|
|
226
272
|
#### `svelte-particles`
|
|
@@ -245,6 +291,28 @@ You can find the instructions [here](https://github.com/matteobruni/tsparticles/
|
|
|
245
291
|
|
|
246
292
|
You can find the instructions [here](https://github.com/matteobruni/tsparticles/blob/main/components/vue3/README.md)
|
|
247
293
|
|
|
294
|
+
### Web Components
|
|
295
|
+
|
|
296
|
+
#### `web-particles`
|
|
297
|
+
|
|
298
|
+
[](https://www.npmjs.com/package/web-particles) [](https://www.npmjs.com/package/web-particles)
|
|
299
|
+
|
|
300
|
+
You can find the instructions [here](https://github.com/matteobruni/tsparticles/blob/main/components/web/README.md)
|
|
301
|
+
|
|
302
|
+
### WordPress
|
|
303
|
+
|
|
304
|
+
Actually an official tsParticles plugin isn't existing, but I have a collaboration with
|
|
305
|
+
the `Premium Addons for Elementor` plugin collection.
|
|
306
|
+
|
|
307
|
+
<div style="float: left; margin-right: 10px;">
|
|
308
|
+
<img width="64" alt="Premium Addons for Elementor" src="https://particles.js.org/images/premium-addons-wordpress-plugin.png" />
|
|
309
|
+
</div>
|
|
310
|
+
<div>
|
|
311
|
+
Premium Addons for Elementor is one of the most common plugins for Elementor that offers more than 55 highly customizable Elementor Widgets and Section Add-ons. tsParticles is exclusively included in Premium Particles Section Add-on for Elementor Page Builder. <a href="https://premiumaddons.com/particles-section-addon-for-elementor-page-builder/" target="_blank">Check It Now</a>.<br />
|
|
312
|
+
Use Premium Addons for Elementor Page Builder and get the chance to include tsParticles in your next WordPress website without the need to write a single line of code. <a href="https://premiumaddons.com/particles-section-addon-for-elementor-page-builder/" target="_blank">See a Live Example</a>.
|
|
313
|
+
</div>
|
|
314
|
+
<div style="clear: both;"></div>
|
|
315
|
+
|
|
248
316
|
---
|
|
249
317
|
|
|
250
318
|
## **_Demo / Generator_**
|
package/Utils/Constants.d.ts
CHANGED
package/Utils/Constants.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.Constants = void 0;
|
|
|
4
4
|
class Constants {
|
|
5
5
|
}
|
|
6
6
|
exports.Constants = Constants;
|
|
7
|
-
Constants.
|
|
7
|
+
Constants.generatedAttribute = "generated";
|
|
8
8
|
Constants.randomColorValue = "random";
|
|
9
9
|
Constants.midColorValue = "mid";
|
|
10
10
|
Constants.touchEndEvent = "touchend";
|
|
@@ -12,6 +12,7 @@ export declare class EventListeners {
|
|
|
12
12
|
private readonly mouseUpHandler;
|
|
13
13
|
private readonly visibilityChangeHandler;
|
|
14
14
|
private readonly themeChangeHandler;
|
|
15
|
+
private readonly oldThemeChangeHandler;
|
|
15
16
|
private readonly resizeHandler;
|
|
16
17
|
private canPush;
|
|
17
18
|
private resizeTimeout?;
|
package/Utils/EventListeners.js
CHANGED
|
@@ -35,6 +35,7 @@ class EventListeners {
|
|
|
35
35
|
this.mouseDownHandler = () => this.mouseDown();
|
|
36
36
|
this.visibilityChangeHandler = () => this.handleVisibilityChange();
|
|
37
37
|
this.themeChangeHandler = (e) => this.handleThemeChange(e);
|
|
38
|
+
this.oldThemeChangeHandler = (e) => this.handleThemeChange(e);
|
|
38
39
|
this.resizeHandler = () => this.handleWindowResize();
|
|
39
40
|
}
|
|
40
41
|
addListeners() {
|
|
@@ -60,9 +61,19 @@ class EventListeners {
|
|
|
60
61
|
else {
|
|
61
62
|
container.interactivity.element = container.canvas.element;
|
|
62
63
|
}
|
|
63
|
-
const mediaMatch = typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)");
|
|
64
|
+
const mediaMatch = !(0, Utils_1.isSsr)() && typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)");
|
|
64
65
|
if (mediaMatch) {
|
|
65
|
-
|
|
66
|
+
if (mediaMatch.addEventListener !== undefined) {
|
|
67
|
+
manageListener(mediaMatch, "change", this.themeChangeHandler, add);
|
|
68
|
+
}
|
|
69
|
+
else if (mediaMatch.addListener !== undefined) {
|
|
70
|
+
if (add) {
|
|
71
|
+
mediaMatch.addListener(this.oldThemeChangeHandler);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
mediaMatch.removeListener(this.oldThemeChangeHandler);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
66
77
|
}
|
|
67
78
|
const interactivityEl = container.interactivity.element;
|
|
68
79
|
if (!interactivityEl) {
|
|
@@ -120,7 +131,7 @@ class EventListeners {
|
|
|
120
131
|
clearTimeout(this.resizeTimeout);
|
|
121
132
|
delete this.resizeTimeout;
|
|
122
133
|
}
|
|
123
|
-
this.resizeTimeout = setTimeout(() => { var _a; return (_a = this.container.canvas) === null || _a === void 0 ? void 0 : _a.windowResize(); }, 500);
|
|
134
|
+
this.resizeTimeout = setTimeout(async () => { var _a; return await ((_a = this.container.canvas) === null || _a === void 0 ? void 0 : _a.windowResize()); }, 500);
|
|
124
135
|
}
|
|
125
136
|
handleVisibilityChange() {
|
|
126
137
|
const container = this.container;
|
package/Utils/Utils.js
CHANGED
|
@@ -200,14 +200,11 @@ function circleBounceDataFromParticle(p) {
|
|
|
200
200
|
}
|
|
201
201
|
exports.circleBounceDataFromParticle = circleBounceDataFromParticle;
|
|
202
202
|
function circleBounce(p1, p2) {
|
|
203
|
-
const xVelocityDiff = p1.velocity.
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
const pos2 = p2.position;
|
|
207
|
-
const xDist = pos2.x - pos1.x;
|
|
208
|
-
const yDist = pos2.y - pos1.y;
|
|
203
|
+
const { x: xVelocityDiff, y: yVelocityDiff } = p1.velocity.sub(p2.velocity);
|
|
204
|
+
const [pos1, pos2] = [p1.position, p2.position];
|
|
205
|
+
const { dx: xDist, dy: yDist } = (0, NumberUtils_1.getDistances)(pos2, pos1);
|
|
209
206
|
if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) {
|
|
210
|
-
const angle = -Math.atan2(
|
|
207
|
+
const angle = -Math.atan2(yDist, xDist);
|
|
211
208
|
const m1 = p1.mass;
|
|
212
209
|
const m2 = p2.mass;
|
|
213
210
|
const u1 = p1.velocity.rotate(angle);
|
package/browser/Core/Canvas.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare class Canvas {
|
|
|
33
33
|
* Initializes the canvas element
|
|
34
34
|
*/
|
|
35
35
|
init(): void;
|
|
36
|
-
loadCanvas(canvas: HTMLCanvasElement
|
|
36
|
+
loadCanvas(canvas: HTMLCanvasElement): void;
|
|
37
37
|
destroy(): void;
|
|
38
38
|
/**
|
|
39
39
|
* Paints the canvas background
|
|
@@ -43,7 +43,7 @@ export declare class Canvas {
|
|
|
43
43
|
* Clears the canvas content
|
|
44
44
|
*/
|
|
45
45
|
clear(): void;
|
|
46
|
-
windowResize(): void
|
|
46
|
+
windowResize(): Promise<void>;
|
|
47
47
|
/**
|
|
48
48
|
* Calculates the size of the canvas
|
|
49
49
|
*/
|
package/browser/Core/Canvas.js
CHANGED
|
@@ -30,15 +30,15 @@ export class Canvas {
|
|
|
30
30
|
this.initBackground();
|
|
31
31
|
this.paint();
|
|
32
32
|
}
|
|
33
|
-
loadCanvas(canvas
|
|
33
|
+
loadCanvas(canvas) {
|
|
34
34
|
var _a;
|
|
35
|
-
if (!canvas.className) {
|
|
36
|
-
canvas.className = Constants.canvasClass;
|
|
37
|
-
}
|
|
38
35
|
if (this.generatedCanvas) {
|
|
39
36
|
(_a = this.element) === null || _a === void 0 ? void 0 : _a.remove();
|
|
40
37
|
}
|
|
41
|
-
this.generatedCanvas =
|
|
38
|
+
this.generatedCanvas =
|
|
39
|
+
canvas.dataset && Constants.generatedAttribute in canvas.dataset
|
|
40
|
+
? canvas.dataset[Constants.generatedAttribute] === "true"
|
|
41
|
+
: this.generatedCanvas;
|
|
42
42
|
this.element = canvas;
|
|
43
43
|
this.originalStyle = deepExtend({}, this.element.style);
|
|
44
44
|
this.size.height = canvas.offsetHeight;
|
|
@@ -89,7 +89,7 @@ export class Canvas {
|
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
windowResize() {
|
|
92
|
+
async windowResize() {
|
|
93
93
|
if (!this.element) {
|
|
94
94
|
return;
|
|
95
95
|
}
|
|
@@ -104,7 +104,7 @@ export class Canvas {
|
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
if (needsRefresh) {
|
|
107
|
-
container.refresh();
|
|
107
|
+
await container.refresh();
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
/**
|
|
@@ -310,6 +310,16 @@ export class Canvas {
|
|
|
310
310
|
element.style.width = originalStyle.width;
|
|
311
311
|
element.style.height = originalStyle.height;
|
|
312
312
|
}
|
|
313
|
+
for (const key in options.style) {
|
|
314
|
+
if (!key || !options.style) {
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
const value = options.style[key];
|
|
318
|
+
if (!value) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
element.style[key] = value;
|
|
322
|
+
}
|
|
313
323
|
}
|
|
314
324
|
paintBase(baseColor) {
|
|
315
325
|
this.draw((ctx) => {
|
package/browser/Core/Loader.js
CHANGED
|
@@ -50,26 +50,21 @@ export class Loader {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
let canvasEl;
|
|
53
|
-
let generatedCanvas;
|
|
54
53
|
if (domContainer.tagName.toLowerCase() === "canvas") {
|
|
55
54
|
canvasEl = domContainer;
|
|
56
|
-
|
|
55
|
+
canvasEl.dataset[Constants.generatedAttribute] = "false";
|
|
57
56
|
}
|
|
58
57
|
else {
|
|
59
58
|
const existingCanvases = domContainer.getElementsByTagName("canvas");
|
|
60
59
|
/* get existing canvas if present, otherwise a new one will be created */
|
|
61
60
|
if (existingCanvases.length) {
|
|
62
61
|
canvasEl = existingCanvases[0];
|
|
63
|
-
|
|
64
|
-
canvasEl.className = Constants.canvasClass;
|
|
65
|
-
}
|
|
66
|
-
generatedCanvas = false;
|
|
62
|
+
canvasEl.dataset[Constants.generatedAttribute] = "false";
|
|
67
63
|
}
|
|
68
64
|
else {
|
|
69
|
-
generatedCanvas = true;
|
|
70
65
|
/* create canvas element */
|
|
71
66
|
canvasEl = document.createElement("canvas");
|
|
72
|
-
canvasEl.
|
|
67
|
+
canvasEl.dataset[Constants.generatedAttribute] = "true";
|
|
73
68
|
/* set size canvas */
|
|
74
69
|
canvasEl.style.width = "100%";
|
|
75
70
|
canvasEl.style.height = "100%";
|
|
@@ -85,7 +80,7 @@ export class Loader {
|
|
|
85
80
|
else {
|
|
86
81
|
dom.push(newItem);
|
|
87
82
|
}
|
|
88
|
-
newItem.canvas.loadCanvas(canvasEl
|
|
83
|
+
newItem.canvas.loadCanvas(canvasEl);
|
|
89
84
|
await newItem.start();
|
|
90
85
|
return newItem;
|
|
91
86
|
}
|
|
@@ -58,6 +58,7 @@ export declare class Options implements IOptions, IOptionLoader<IOptions> {
|
|
|
58
58
|
pauseOnBlur: boolean;
|
|
59
59
|
pauseOnOutsideViewport: boolean;
|
|
60
60
|
preset?: string | string[];
|
|
61
|
+
style: RecursivePartial<CSSStyleDeclaration>;
|
|
61
62
|
responsive: Responsive[];
|
|
62
63
|
themes: Theme[];
|
|
63
64
|
zLayers: number;
|
|
@@ -8,7 +8,7 @@ import { Interactivity } from "./Interactivity/Interactivity";
|
|
|
8
8
|
import { ParticlesOptions } from "./Particles/ParticlesOptions";
|
|
9
9
|
import { BackgroundMask } from "./BackgroundMask/BackgroundMask";
|
|
10
10
|
import { Background } from "./Background/Background";
|
|
11
|
-
import { Plugins } from "../../Utils";
|
|
11
|
+
import { deepExtend, Plugins } from "../../Utils";
|
|
12
12
|
import { Theme } from "./Theme/Theme";
|
|
13
13
|
import { ResponsiveMode, ThemeMode } from "../../Enums";
|
|
14
14
|
import { FullScreen } from "./FullScreen/FullScreen";
|
|
@@ -36,6 +36,7 @@ export class Options {
|
|
|
36
36
|
this.pauseOnBlur = true;
|
|
37
37
|
this.pauseOnOutsideViewport = true;
|
|
38
38
|
this.responsive = [];
|
|
39
|
+
this.style = {};
|
|
39
40
|
this.themes = [];
|
|
40
41
|
this.zLayers = 100;
|
|
41
42
|
}
|
|
@@ -140,6 +141,7 @@ export class Options {
|
|
|
140
141
|
}
|
|
141
142
|
this.motion.load(data.motion);
|
|
142
143
|
this.particles.load(data.particles);
|
|
144
|
+
this.style = deepExtend(this.style, data.style);
|
|
143
145
|
Plugins.loadOptions(this, data);
|
|
144
146
|
if (data.responsive !== undefined) {
|
|
145
147
|
for (const responsive of data.responsive) {
|
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
* @category Utils
|
|
4
4
|
*/
|
|
5
5
|
export declare class Constants {
|
|
6
|
-
|
|
7
|
-
* Particles canvas element class name
|
|
8
|
-
*/
|
|
9
|
-
static readonly canvasClass: string;
|
|
6
|
+
static readonly generatedAttribute: string;
|
|
10
7
|
static readonly randomColorValue: string;
|
|
11
8
|
static readonly midColorValue: string;
|
|
12
9
|
static readonly touchEndEvent: string;
|
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export class Constants {
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
* Particles canvas element class name
|
|
9
|
-
*/
|
|
10
|
-
Constants.canvasClass = "tsparticles-canvas-el";
|
|
7
|
+
Constants.generatedAttribute = "generated";
|
|
11
8
|
Constants.randomColorValue = "random";
|
|
12
9
|
Constants.midColorValue = "mid";
|
|
13
10
|
Constants.touchEndEvent = "touchend";
|
|
@@ -16,6 +16,7 @@ export declare class EventListeners {
|
|
|
16
16
|
private readonly mouseUpHandler;
|
|
17
17
|
private readonly visibilityChangeHandler;
|
|
18
18
|
private readonly themeChangeHandler;
|
|
19
|
+
private readonly oldThemeChangeHandler;
|
|
19
20
|
private readonly resizeHandler;
|
|
20
21
|
private canPush;
|
|
21
22
|
private resizeTimeout?;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ClickMode, InteractivityDetect } from "../Enums";
|
|
2
2
|
import { Constants } from "./Constants";
|
|
3
|
-
import { itemFromArray } from "./Utils";
|
|
3
|
+
import { isSsr, itemFromArray } from "./Utils";
|
|
4
4
|
function manageListener(element, event, handler, add, options) {
|
|
5
5
|
if (add) {
|
|
6
6
|
let addOptions = { passive: true };
|
|
@@ -40,6 +40,7 @@ export class EventListeners {
|
|
|
40
40
|
this.mouseDownHandler = () => this.mouseDown();
|
|
41
41
|
this.visibilityChangeHandler = () => this.handleVisibilityChange();
|
|
42
42
|
this.themeChangeHandler = (e) => this.handleThemeChange(e);
|
|
43
|
+
this.oldThemeChangeHandler = (e) => this.handleThemeChange(e);
|
|
43
44
|
this.resizeHandler = () => this.handleWindowResize();
|
|
44
45
|
}
|
|
45
46
|
/**
|
|
@@ -75,9 +76,19 @@ export class EventListeners {
|
|
|
75
76
|
else {
|
|
76
77
|
container.interactivity.element = container.canvas.element;
|
|
77
78
|
}
|
|
78
|
-
const mediaMatch = typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)");
|
|
79
|
+
const mediaMatch = !isSsr() && typeof matchMedia !== "undefined" && matchMedia("(prefers-color-scheme: dark)");
|
|
79
80
|
if (mediaMatch) {
|
|
80
|
-
|
|
81
|
+
if (mediaMatch.addEventListener !== undefined) {
|
|
82
|
+
manageListener(mediaMatch, "change", this.themeChangeHandler, add);
|
|
83
|
+
}
|
|
84
|
+
else if (mediaMatch.addListener !== undefined) {
|
|
85
|
+
if (add) {
|
|
86
|
+
mediaMatch.addListener(this.oldThemeChangeHandler);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
mediaMatch.removeListener(this.oldThemeChangeHandler);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
81
92
|
}
|
|
82
93
|
const interactivityEl = container.interactivity.element;
|
|
83
94
|
/* detect mouse pos - on hover / click event */
|
|
@@ -142,7 +153,7 @@ export class EventListeners {
|
|
|
142
153
|
clearTimeout(this.resizeTimeout);
|
|
143
154
|
delete this.resizeTimeout;
|
|
144
155
|
}
|
|
145
|
-
this.resizeTimeout = setTimeout(() => { var _a; return (_a = this.container.canvas) === null || _a === void 0 ? void 0 : _a.windowResize(); }, 500);
|
|
156
|
+
this.resizeTimeout = setTimeout(async () => { var _a; return await ((_a = this.container.canvas) === null || _a === void 0 ? void 0 : _a.windowResize()); }, 500);
|
|
146
157
|
}
|
|
147
158
|
handleVisibilityChange() {
|
|
148
159
|
const container = this.container;
|
package/browser/Utils/Utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OutModeDirection } from "../Enums";
|
|
2
|
-
import { collisionVelocity, getValue } from "./NumberUtils";
|
|
2
|
+
import { collisionVelocity, getValue, getDistances } from "./NumberUtils";
|
|
3
3
|
import { Vector } from "../Core/Particle/Vector";
|
|
4
4
|
function rectSideBounce(pSide, pOtherSide, rectSide, rectOtherSide, velocity, factor) {
|
|
5
5
|
const res = { bounced: false };
|
|
@@ -188,16 +188,13 @@ export function circleBounceDataFromParticle(p) {
|
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
190
|
export function circleBounce(p1, p2) {
|
|
191
|
-
const xVelocityDiff = p1.velocity.
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
const pos2 = p2.position;
|
|
195
|
-
const xDist = pos2.x - pos1.x;
|
|
196
|
-
const yDist = pos2.y - pos1.y;
|
|
191
|
+
const { x: xVelocityDiff, y: yVelocityDiff } = p1.velocity.sub(p2.velocity);
|
|
192
|
+
const [pos1, pos2] = [p1.position, p2.position];
|
|
193
|
+
const { dx: xDist, dy: yDist } = getDistances(pos2, pos1);
|
|
197
194
|
// Prevent accidental overlap of particles
|
|
198
195
|
if (xVelocityDiff * xDist + yVelocityDiff * yDist >= 0) {
|
|
199
196
|
// Grab angle between the two colliding particles
|
|
200
|
-
const angle = -Math.atan2(
|
|
197
|
+
const angle = -Math.atan2(yDist, xDist);
|
|
201
198
|
// Store mass in var for better readability in collision equation
|
|
202
199
|
const m1 = p1.mass;
|
|
203
200
|
const m2 = p2.mass;
|
package/esm/Core/Canvas.d.ts
CHANGED
|
@@ -13,11 +13,11 @@ export declare class Canvas {
|
|
|
13
13
|
private originalStyle?;
|
|
14
14
|
constructor(container: Container);
|
|
15
15
|
init(): void;
|
|
16
|
-
loadCanvas(canvas: HTMLCanvasElement
|
|
16
|
+
loadCanvas(canvas: HTMLCanvasElement): void;
|
|
17
17
|
destroy(): void;
|
|
18
18
|
paint(): void;
|
|
19
19
|
clear(): void;
|
|
20
|
-
windowResize(): void
|
|
20
|
+
windowResize(): Promise<void>;
|
|
21
21
|
resize(): void;
|
|
22
22
|
drawConnectLine(p1: IParticle, p2: IParticle): void;
|
|
23
23
|
drawGrabLine(particle: IParticle, lineColor: IRgb, opacity: number, mousePos: ICoordinates): void;
|
package/esm/Core/Canvas.js
CHANGED
|
@@ -18,15 +18,15 @@ export class Canvas {
|
|
|
18
18
|
this.initBackground();
|
|
19
19
|
this.paint();
|
|
20
20
|
}
|
|
21
|
-
loadCanvas(canvas
|
|
21
|
+
loadCanvas(canvas) {
|
|
22
22
|
var _a;
|
|
23
|
-
if (!canvas.className) {
|
|
24
|
-
canvas.className = Constants.canvasClass;
|
|
25
|
-
}
|
|
26
23
|
if (this.generatedCanvas) {
|
|
27
24
|
(_a = this.element) === null || _a === void 0 ? void 0 : _a.remove();
|
|
28
25
|
}
|
|
29
|
-
this.generatedCanvas =
|
|
26
|
+
this.generatedCanvas =
|
|
27
|
+
canvas.dataset && Constants.generatedAttribute in canvas.dataset
|
|
28
|
+
? canvas.dataset[Constants.generatedAttribute] === "true"
|
|
29
|
+
: this.generatedCanvas;
|
|
30
30
|
this.element = canvas;
|
|
31
31
|
this.originalStyle = deepExtend({}, this.element.style);
|
|
32
32
|
this.size.height = canvas.offsetHeight;
|
|
@@ -71,7 +71,7 @@ export class Canvas {
|
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
windowResize() {
|
|
74
|
+
async windowResize() {
|
|
75
75
|
if (!this.element) {
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
@@ -85,7 +85,7 @@ export class Canvas {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
if (needsRefresh) {
|
|
88
|
-
container.refresh();
|
|
88
|
+
await container.refresh();
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
resize() {
|
|
@@ -288,6 +288,16 @@ export class Canvas {
|
|
|
288
288
|
element.style.width = originalStyle.width;
|
|
289
289
|
element.style.height = originalStyle.height;
|
|
290
290
|
}
|
|
291
|
+
for (const key in options.style) {
|
|
292
|
+
if (!key || !options.style) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const value = options.style[key];
|
|
296
|
+
if (!value) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
element.style[key] = value;
|
|
300
|
+
}
|
|
291
301
|
}
|
|
292
302
|
paintBase(baseColor) {
|
|
293
303
|
this.draw((ctx) => {
|