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.
Files changed (42) hide show
  1. package/Core/Canvas.d.ts +2 -2
  2. package/Core/Canvas.js +17 -7
  3. package/Core/Loader.js +4 -9
  4. package/Options/Classes/Options.d.ts +1 -0
  5. package/Options/Classes/Options.js +2 -0
  6. package/Options/Interfaces/IOptions.d.ts +1 -0
  7. package/README.md +68 -0
  8. package/Utils/Constants.d.ts +1 -1
  9. package/Utils/Constants.js +1 -1
  10. package/Utils/EventListeners.d.ts +1 -0
  11. package/Utils/EventListeners.js +14 -3
  12. package/Utils/Utils.js +4 -7
  13. package/browser/Core/Canvas.d.ts +2 -2
  14. package/browser/Core/Canvas.js +17 -7
  15. package/browser/Core/Loader.js +4 -9
  16. package/browser/Options/Classes/Options.d.ts +1 -0
  17. package/browser/Options/Classes/Options.js +3 -1
  18. package/browser/Options/Interfaces/IOptions.d.ts +1 -0
  19. package/browser/Utils/Constants.d.ts +1 -4
  20. package/browser/Utils/Constants.js +1 -4
  21. package/browser/Utils/EventListeners.d.ts +1 -0
  22. package/browser/Utils/EventListeners.js +15 -4
  23. package/browser/Utils/Utils.js +5 -8
  24. package/esm/Core/Canvas.d.ts +2 -2
  25. package/esm/Core/Canvas.js +17 -7
  26. package/esm/Core/Loader.js +4 -9
  27. package/esm/Options/Classes/Options.d.ts +1 -0
  28. package/esm/Options/Classes/Options.js +3 -1
  29. package/esm/Options/Interfaces/IOptions.d.ts +1 -0
  30. package/esm/Utils/Constants.d.ts +1 -1
  31. package/esm/Utils/Constants.js +1 -1
  32. package/esm/Utils/EventListeners.d.ts +1 -0
  33. package/esm/Utils/EventListeners.js +15 -4
  34. package/esm/Utils/Utils.js +5 -8
  35. package/package.json +1 -1
  36. package/report.html +2 -2
  37. package/report.slim.html +2 -2
  38. package/scripts/install.js +14 -3
  39. package/tsparticles.js +38 -28
  40. package/tsparticles.min.js +2 -2
  41. package/tsparticles.slim.js +38 -28
  42. 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, generatedCanvas?: boolean): void;
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, generatedCanvas) {
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 = generatedCanvas !== null && generatedCanvas !== void 0 ? generatedCanvas : 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
- generatedCanvas = false;
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
- if (!canvasEl.className) {
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.className = Utils_1.Constants.canvasClass;
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, generatedCanvas);
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) {
@@ -27,6 +27,7 @@ export interface IOptions {
27
27
  preset?: SingleOrMultiple<string>;
28
28
  responsive: IResponsive[];
29
29
  retina_detect: boolean;
30
+ style: RecursivePartial<CSSStyleDeclaration>;
30
31
  themes: ITheme[];
31
32
  zLayers: number;
32
33
  [name: string]: unknown;
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
+ [![npm](https://img.shields.io/npm/v/riot-particles)](https://www.npmjs.com/package/riot-particles) [![npm](https://img.shields.io/npm/dm/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
+ [![npm](https://img.shields.io/npm/v/solid-particles)](https://www.npmjs.com/package/solid-particles) [![npm](https://img.shields.io/npm/dm/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
+ [![npm](https://img.shields.io/npm/v/web-particles)](https://www.npmjs.com/package/web-particles) [![npm](https://img.shields.io/npm/dm/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_**
@@ -1,5 +1,5 @@
1
1
  export declare class Constants {
2
- static readonly canvasClass: string;
2
+ static readonly generatedAttribute: string;
3
3
  static readonly randomColorValue: string;
4
4
  static readonly midColorValue: string;
5
5
  static readonly touchEndEvent: string;
@@ -4,7 +4,7 @@ exports.Constants = void 0;
4
4
  class Constants {
5
5
  }
6
6
  exports.Constants = Constants;
7
- Constants.canvasClass = "tsparticles-canvas-el";
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?;
@@ -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
- manageListener(mediaMatch, "change", this.themeChangeHandler, add);
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.x;
204
- const yVelocityDiff = p1.velocity.y;
205
- const pos1 = p1.position;
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(pos2.y - pos1.y, pos2.x - pos1.x);
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);
@@ -33,7 +33,7 @@ export declare class Canvas {
33
33
  * Initializes the canvas element
34
34
  */
35
35
  init(): void;
36
- loadCanvas(canvas: HTMLCanvasElement, generatedCanvas?: boolean): void;
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
  */
@@ -30,15 +30,15 @@ export class Canvas {
30
30
  this.initBackground();
31
31
  this.paint();
32
32
  }
33
- loadCanvas(canvas, generatedCanvas) {
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 = generatedCanvas !== null && generatedCanvas !== void 0 ? generatedCanvas : 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) => {
@@ -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
- generatedCanvas = false;
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
- if (!canvasEl.className) {
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.className = Constants.canvasClass;
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, generatedCanvas);
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) {
@@ -89,6 +89,7 @@ export interface IOptions {
89
89
  * @deprecated use the new detectRetina instead
90
90
  */
91
91
  retina_detect: boolean;
92
+ style: RecursivePartial<CSSStyleDeclaration>;
92
93
  /**
93
94
  * User-defined themes that can be retrieved by the particles [[Container]]
94
95
  */
@@ -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
- manageListener(mediaMatch, "change", this.themeChangeHandler, add);
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;
@@ -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.x;
192
- const yVelocityDiff = p1.velocity.y;
193
- const pos1 = p1.position;
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(pos2.y - pos1.y, pos2.x - pos1.x);
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;
@@ -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, generatedCanvas?: boolean): void;
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;
@@ -18,15 +18,15 @@ export class Canvas {
18
18
  this.initBackground();
19
19
  this.paint();
20
20
  }
21
- loadCanvas(canvas, generatedCanvas) {
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 = generatedCanvas !== null && generatedCanvas !== void 0 ? generatedCanvas : 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) => {