@tsparticles/plugin-emitters-shape-path 3.0.2 → 3.1.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.
@@ -1,6 +1,7 @@
1
1
  import { EmitterShapeBase } from "@tsparticles/plugin-emitters";
2
- import { errorPrefix } from "@tsparticles/engine";
2
+ import { errorPrefix, percentDenominator } from "@tsparticles/engine";
3
3
  import { generateRandomPointOnPathPerimeter, generateRandomPointWithinPath } from "./utils.js";
4
+ const half = 0.5;
4
5
  export class EmittersPathShape extends EmitterShapeBase {
5
6
  constructor(position, size, fill, options) {
6
7
  super(position, size, fill, options);
@@ -11,25 +12,26 @@ export class EmittersPathShape extends EmitterShapeBase {
11
12
  this.checkContext = ctx;
12
13
  this.points = options.points;
13
14
  const pathData = this.points, path = new Path2D(), offset = {
14
- x: position.x - size.width / 2,
15
- y: position.y - size.height / 2,
15
+ x: position.x - size.width * half,
16
+ y: position.y - size.height * half,
16
17
  };
17
18
  for (const [index, point] of pathData.entries()) {
18
19
  const coords = {
19
- x: offset.x + (point.x * size.width) / 100,
20
- y: offset.y + (point.y * size.height) / 100,
20
+ x: offset.x + (point.x * size.width) / percentDenominator,
21
+ y: offset.y + (point.y * size.height) / percentDenominator,
21
22
  };
22
- if (index === 0) {
23
+ if (!index) {
23
24
  path.moveTo(coords.x, coords.y);
24
25
  }
25
26
  else {
26
27
  path.lineTo(coords.x, coords.y);
27
28
  }
28
29
  }
29
- if (pathData[0]) {
30
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
31
+ if (firstPathData) {
30
32
  const coords = {
31
- x: offset.x + (pathData[0].x * size.width) / 100,
32
- y: offset.y + (pathData[0].y * size.height) / 100,
33
+ x: offset.x + (firstPathData.x * size.width) / percentDenominator,
34
+ y: offset.y + (firstPathData.y * size.height) / percentDenominator,
33
35
  };
34
36
  path.lineTo(coords.x, coords.y);
35
37
  }
@@ -41,30 +43,31 @@ export class EmittersPathShape extends EmitterShapeBase {
41
43
  const ctx = this.checkContext, position = this.position, size = this.size, fill = this.fill, path = this.path, res = fill
42
44
  ? generateRandomPointWithinPath(ctx, path, position, size)
43
45
  : generateRandomPointOnPathPerimeter(ctx, path, position, size);
44
- return res ? { position: res } : null;
46
+ return Promise.resolve(res ? { position: res } : null);
45
47
  }
46
48
  resize(position, size) {
47
49
  super.resize(position, size);
48
50
  const pathData = this.points, path = new Path2D(), offset = {
49
- x: position.x - size.width / 2,
50
- y: position.y - size.height / 2,
51
+ x: position.x - size.width * half,
52
+ y: position.y - size.height * half,
51
53
  };
52
54
  for (const [index, point] of pathData.entries()) {
53
55
  const coords = {
54
- x: offset.x + (point.x * size.width) / 100,
55
- y: offset.y + (point.y * size.height) / 100,
56
+ x: offset.x + (point.x * size.width) / percentDenominator,
57
+ y: offset.y + (point.y * size.height) / percentDenominator,
56
58
  };
57
- if (index === 0) {
59
+ if (!index) {
58
60
  path.moveTo(coords.x, coords.y);
59
61
  }
60
62
  else {
61
63
  path.lineTo(coords.x, coords.y);
62
64
  }
63
65
  }
64
- if (pathData[0]) {
66
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
67
+ if (firstPathData) {
65
68
  const coords = {
66
- x: offset.x + (pathData[0].x * size.width) / 100,
67
- y: offset.y + (pathData[0].y * size.height) / 100,
69
+ x: offset.x + (firstPathData.x * size.width) / percentDenominator,
70
+ y: offset.y + (firstPathData.y * size.height) / percentDenominator,
68
71
  };
69
72
  path.lineTo(coords.x, coords.y);
70
73
  }
@@ -1,3 +1,4 @@
1
+ const defaultPosition = { x: 50, y: 50 };
1
2
  export class EmittersPathShapeOptions {
2
3
  constructor() {
3
4
  this.points = [];
@@ -7,7 +8,7 @@ export class EmittersPathShapeOptions {
7
8
  return;
8
9
  }
9
10
  if (data.points !== undefined) {
10
- this.points = data.points.map((t) => ({ x: t.x ?? 50, y: t.y ?? 50 }));
11
+ this.points = data.points.map((t) => ({ x: t.x ?? defaultPosition.x, y: t.y ?? defaultPosition.y }));
11
12
  }
12
13
  }
13
14
  }
package/browser/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { EmittersPathShapeGenerator } from "./EmittersPathShapeGenerator.js";
2
2
  export async function loadEmittersShapePath(engine, refresh = true) {
3
3
  const emittersEngine = engine;
4
- emittersEngine.addEmitterShapeGenerator &&
5
- emittersEngine.addEmitterShapeGenerator("path", new EmittersPathShapeGenerator());
4
+ emittersEngine.addEmitterShapeGenerator?.("path", new EmittersPathShapeGenerator());
6
5
  await emittersEngine.refresh(refresh);
7
6
  }
package/browser/utils.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { getRandom } from "@tsparticles/engine";
2
+ const maxAttempts = 100, half = 0.5;
2
3
  export function generateRandomPointWithinPath(ctx, path, center, size) {
3
4
  let randomPoint = null;
4
- for (let attempts = 0; attempts < 100; attempts++) {
5
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
5
6
  const tmpPoint = {
6
- x: center.x + getRandom() * size.width - size.width / 2,
7
- y: center.y + getRandom() * size.height - size.height / 2,
7
+ x: center.x + getRandom() * size.width - size.width * half,
8
+ y: center.y + getRandom() * size.height - size.height * half,
8
9
  };
9
10
  if (ctx.isPointInPath(path, tmpPoint.x, tmpPoint.y)) {
10
11
  randomPoint = tmpPoint;
@@ -15,10 +16,10 @@ export function generateRandomPointWithinPath(ctx, path, center, size) {
15
16
  }
16
17
  export function generateRandomPointOnPathPerimeter(ctx, path, center, size) {
17
18
  let randomPoint = null;
18
- for (let attempts = 0; attempts < 100; attempts++) {
19
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
19
20
  const tmpPoint = {
20
- x: center.x + getRandom() * size.width - size.width / 2,
21
- y: center.y + getRandom() * size.height - size.height / 2,
21
+ x: center.x + getRandom() * size.width - size.width * half,
22
+ y: center.y + getRandom() * size.height - size.height * half,
22
23
  };
23
24
  if (ctx.isPointInStroke(path, tmpPoint.x, tmpPoint.y)) {
24
25
  randomPoint = tmpPoint;
@@ -4,6 +4,7 @@ exports.EmittersPathShape = void 0;
4
4
  const plugin_emitters_1 = require("@tsparticles/plugin-emitters");
5
5
  const engine_1 = require("@tsparticles/engine");
6
6
  const utils_js_1 = require("./utils.js");
7
+ const half = 0.5;
7
8
  class EmittersPathShape extends plugin_emitters_1.EmitterShapeBase {
8
9
  constructor(position, size, fill, options) {
9
10
  super(position, size, fill, options);
@@ -14,25 +15,26 @@ class EmittersPathShape extends plugin_emitters_1.EmitterShapeBase {
14
15
  this.checkContext = ctx;
15
16
  this.points = options.points;
16
17
  const pathData = this.points, path = new Path2D(), offset = {
17
- x: position.x - size.width / 2,
18
- y: position.y - size.height / 2,
18
+ x: position.x - size.width * half,
19
+ y: position.y - size.height * half,
19
20
  };
20
21
  for (const [index, point] of pathData.entries()) {
21
22
  const coords = {
22
- x: offset.x + (point.x * size.width) / 100,
23
- y: offset.y + (point.y * size.height) / 100,
23
+ x: offset.x + (point.x * size.width) / engine_1.percentDenominator,
24
+ y: offset.y + (point.y * size.height) / engine_1.percentDenominator,
24
25
  };
25
- if (index === 0) {
26
+ if (!index) {
26
27
  path.moveTo(coords.x, coords.y);
27
28
  }
28
29
  else {
29
30
  path.lineTo(coords.x, coords.y);
30
31
  }
31
32
  }
32
- if (pathData[0]) {
33
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
34
+ if (firstPathData) {
33
35
  const coords = {
34
- x: offset.x + (pathData[0].x * size.width) / 100,
35
- y: offset.y + (pathData[0].y * size.height) / 100,
36
+ x: offset.x + (firstPathData.x * size.width) / engine_1.percentDenominator,
37
+ y: offset.y + (firstPathData.y * size.height) / engine_1.percentDenominator,
36
38
  };
37
39
  path.lineTo(coords.x, coords.y);
38
40
  }
@@ -44,30 +46,31 @@ class EmittersPathShape extends plugin_emitters_1.EmitterShapeBase {
44
46
  const ctx = this.checkContext, position = this.position, size = this.size, fill = this.fill, path = this.path, res = fill
45
47
  ? (0, utils_js_1.generateRandomPointWithinPath)(ctx, path, position, size)
46
48
  : (0, utils_js_1.generateRandomPointOnPathPerimeter)(ctx, path, position, size);
47
- return res ? { position: res } : null;
49
+ return Promise.resolve(res ? { position: res } : null);
48
50
  }
49
51
  resize(position, size) {
50
52
  super.resize(position, size);
51
53
  const pathData = this.points, path = new Path2D(), offset = {
52
- x: position.x - size.width / 2,
53
- y: position.y - size.height / 2,
54
+ x: position.x - size.width * half,
55
+ y: position.y - size.height * half,
54
56
  };
55
57
  for (const [index, point] of pathData.entries()) {
56
58
  const coords = {
57
- x: offset.x + (point.x * size.width) / 100,
58
- y: offset.y + (point.y * size.height) / 100,
59
+ x: offset.x + (point.x * size.width) / engine_1.percentDenominator,
60
+ y: offset.y + (point.y * size.height) / engine_1.percentDenominator,
59
61
  };
60
- if (index === 0) {
62
+ if (!index) {
61
63
  path.moveTo(coords.x, coords.y);
62
64
  }
63
65
  else {
64
66
  path.lineTo(coords.x, coords.y);
65
67
  }
66
68
  }
67
- if (pathData[0]) {
69
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
70
+ if (firstPathData) {
68
71
  const coords = {
69
- x: offset.x + (pathData[0].x * size.width) / 100,
70
- y: offset.y + (pathData[0].y * size.height) / 100,
72
+ x: offset.x + (firstPathData.x * size.width) / engine_1.percentDenominator,
73
+ y: offset.y + (firstPathData.y * size.height) / engine_1.percentDenominator,
71
74
  };
72
75
  path.lineTo(coords.x, coords.y);
73
76
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EmittersPathShapeOptions = void 0;
4
+ const defaultPosition = { x: 50, y: 50 };
4
5
  class EmittersPathShapeOptions {
5
6
  constructor() {
6
7
  this.points = [];
@@ -10,7 +11,7 @@ class EmittersPathShapeOptions {
10
11
  return;
11
12
  }
12
13
  if (data.points !== undefined) {
13
- this.points = data.points.map((t) => ({ x: t.x ?? 50, y: t.y ?? 50 }));
14
+ this.points = data.points.map((t) => ({ x: t.x ?? defaultPosition.x, y: t.y ?? defaultPosition.y }));
14
15
  }
15
16
  }
16
17
  }
package/cjs/index.js CHANGED
@@ -4,8 +4,7 @@ exports.loadEmittersShapePath = void 0;
4
4
  const EmittersPathShapeGenerator_js_1 = require("./EmittersPathShapeGenerator.js");
5
5
  async function loadEmittersShapePath(engine, refresh = true) {
6
6
  const emittersEngine = engine;
7
- emittersEngine.addEmitterShapeGenerator &&
8
- emittersEngine.addEmitterShapeGenerator("path", new EmittersPathShapeGenerator_js_1.EmittersPathShapeGenerator());
7
+ emittersEngine.addEmitterShapeGenerator?.("path", new EmittersPathShapeGenerator_js_1.EmittersPathShapeGenerator());
9
8
  await emittersEngine.refresh(refresh);
10
9
  }
11
10
  exports.loadEmittersShapePath = loadEmittersShapePath;
package/cjs/utils.js CHANGED
@@ -2,12 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateRandomPointOnPathPerimeter = exports.generateRandomPointWithinPath = void 0;
4
4
  const engine_1 = require("@tsparticles/engine");
5
+ const maxAttempts = 100, half = 0.5;
5
6
  function generateRandomPointWithinPath(ctx, path, center, size) {
6
7
  let randomPoint = null;
7
- for (let attempts = 0; attempts < 100; attempts++) {
8
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
8
9
  const tmpPoint = {
9
- x: center.x + (0, engine_1.getRandom)() * size.width - size.width / 2,
10
- y: center.y + (0, engine_1.getRandom)() * size.height - size.height / 2,
10
+ x: center.x + (0, engine_1.getRandom)() * size.width - size.width * half,
11
+ y: center.y + (0, engine_1.getRandom)() * size.height - size.height * half,
11
12
  };
12
13
  if (ctx.isPointInPath(path, tmpPoint.x, tmpPoint.y)) {
13
14
  randomPoint = tmpPoint;
@@ -19,10 +20,10 @@ function generateRandomPointWithinPath(ctx, path, center, size) {
19
20
  exports.generateRandomPointWithinPath = generateRandomPointWithinPath;
20
21
  function generateRandomPointOnPathPerimeter(ctx, path, center, size) {
21
22
  let randomPoint = null;
22
- for (let attempts = 0; attempts < 100; attempts++) {
23
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
23
24
  const tmpPoint = {
24
- x: center.x + (0, engine_1.getRandom)() * size.width - size.width / 2,
25
- y: center.y + (0, engine_1.getRandom)() * size.height - size.height / 2,
25
+ x: center.x + (0, engine_1.getRandom)() * size.width - size.width * half,
26
+ y: center.y + (0, engine_1.getRandom)() * size.height - size.height * half,
26
27
  };
27
28
  if (ctx.isPointInStroke(path, tmpPoint.x, tmpPoint.y)) {
28
29
  randomPoint = tmpPoint;
@@ -1,6 +1,7 @@
1
1
  import { EmitterShapeBase } from "@tsparticles/plugin-emitters";
2
- import { errorPrefix } from "@tsparticles/engine";
2
+ import { errorPrefix, percentDenominator } from "@tsparticles/engine";
3
3
  import { generateRandomPointOnPathPerimeter, generateRandomPointWithinPath } from "./utils.js";
4
+ const half = 0.5;
4
5
  export class EmittersPathShape extends EmitterShapeBase {
5
6
  constructor(position, size, fill, options) {
6
7
  super(position, size, fill, options);
@@ -11,25 +12,26 @@ export class EmittersPathShape extends EmitterShapeBase {
11
12
  this.checkContext = ctx;
12
13
  this.points = options.points;
13
14
  const pathData = this.points, path = new Path2D(), offset = {
14
- x: position.x - size.width / 2,
15
- y: position.y - size.height / 2,
15
+ x: position.x - size.width * half,
16
+ y: position.y - size.height * half,
16
17
  };
17
18
  for (const [index, point] of pathData.entries()) {
18
19
  const coords = {
19
- x: offset.x + (point.x * size.width) / 100,
20
- y: offset.y + (point.y * size.height) / 100,
20
+ x: offset.x + (point.x * size.width) / percentDenominator,
21
+ y: offset.y + (point.y * size.height) / percentDenominator,
21
22
  };
22
- if (index === 0) {
23
+ if (!index) {
23
24
  path.moveTo(coords.x, coords.y);
24
25
  }
25
26
  else {
26
27
  path.lineTo(coords.x, coords.y);
27
28
  }
28
29
  }
29
- if (pathData[0]) {
30
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
31
+ if (firstPathData) {
30
32
  const coords = {
31
- x: offset.x + (pathData[0].x * size.width) / 100,
32
- y: offset.y + (pathData[0].y * size.height) / 100,
33
+ x: offset.x + (firstPathData.x * size.width) / percentDenominator,
34
+ y: offset.y + (firstPathData.y * size.height) / percentDenominator,
33
35
  };
34
36
  path.lineTo(coords.x, coords.y);
35
37
  }
@@ -41,30 +43,31 @@ export class EmittersPathShape extends EmitterShapeBase {
41
43
  const ctx = this.checkContext, position = this.position, size = this.size, fill = this.fill, path = this.path, res = fill
42
44
  ? generateRandomPointWithinPath(ctx, path, position, size)
43
45
  : generateRandomPointOnPathPerimeter(ctx, path, position, size);
44
- return res ? { position: res } : null;
46
+ return Promise.resolve(res ? { position: res } : null);
45
47
  }
46
48
  resize(position, size) {
47
49
  super.resize(position, size);
48
50
  const pathData = this.points, path = new Path2D(), offset = {
49
- x: position.x - size.width / 2,
50
- y: position.y - size.height / 2,
51
+ x: position.x - size.width * half,
52
+ y: position.y - size.height * half,
51
53
  };
52
54
  for (const [index, point] of pathData.entries()) {
53
55
  const coords = {
54
- x: offset.x + (point.x * size.width) / 100,
55
- y: offset.y + (point.y * size.height) / 100,
56
+ x: offset.x + (point.x * size.width) / percentDenominator,
57
+ y: offset.y + (point.y * size.height) / percentDenominator,
56
58
  };
57
- if (index === 0) {
59
+ if (!index) {
58
60
  path.moveTo(coords.x, coords.y);
59
61
  }
60
62
  else {
61
63
  path.lineTo(coords.x, coords.y);
62
64
  }
63
65
  }
64
- if (pathData[0]) {
66
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
67
+ if (firstPathData) {
65
68
  const coords = {
66
- x: offset.x + (pathData[0].x * size.width) / 100,
67
- y: offset.y + (pathData[0].y * size.height) / 100,
69
+ x: offset.x + (firstPathData.x * size.width) / percentDenominator,
70
+ y: offset.y + (firstPathData.y * size.height) / percentDenominator,
68
71
  };
69
72
  path.lineTo(coords.x, coords.y);
70
73
  }
@@ -1,3 +1,4 @@
1
+ const defaultPosition = { x: 50, y: 50 };
1
2
  export class EmittersPathShapeOptions {
2
3
  constructor() {
3
4
  this.points = [];
@@ -7,7 +8,7 @@ export class EmittersPathShapeOptions {
7
8
  return;
8
9
  }
9
10
  if (data.points !== undefined) {
10
- this.points = data.points.map((t) => ({ x: t.x ?? 50, y: t.y ?? 50 }));
11
+ this.points = data.points.map((t) => ({ x: t.x ?? defaultPosition.x, y: t.y ?? defaultPosition.y }));
11
12
  }
12
13
  }
13
14
  }
package/esm/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { EmittersPathShapeGenerator } from "./EmittersPathShapeGenerator.js";
2
2
  export async function loadEmittersShapePath(engine, refresh = true) {
3
3
  const emittersEngine = engine;
4
- emittersEngine.addEmitterShapeGenerator &&
5
- emittersEngine.addEmitterShapeGenerator("path", new EmittersPathShapeGenerator());
4
+ emittersEngine.addEmitterShapeGenerator?.("path", new EmittersPathShapeGenerator());
6
5
  await emittersEngine.refresh(refresh);
7
6
  }
package/esm/utils.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { getRandom } from "@tsparticles/engine";
2
+ const maxAttempts = 100, half = 0.5;
2
3
  export function generateRandomPointWithinPath(ctx, path, center, size) {
3
4
  let randomPoint = null;
4
- for (let attempts = 0; attempts < 100; attempts++) {
5
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
5
6
  const tmpPoint = {
6
- x: center.x + getRandom() * size.width - size.width / 2,
7
- y: center.y + getRandom() * size.height - size.height / 2,
7
+ x: center.x + getRandom() * size.width - size.width * half,
8
+ y: center.y + getRandom() * size.height - size.height * half,
8
9
  };
9
10
  if (ctx.isPointInPath(path, tmpPoint.x, tmpPoint.y)) {
10
11
  randomPoint = tmpPoint;
@@ -15,10 +16,10 @@ export function generateRandomPointWithinPath(ctx, path, center, size) {
15
16
  }
16
17
  export function generateRandomPointOnPathPerimeter(ctx, path, center, size) {
17
18
  let randomPoint = null;
18
- for (let attempts = 0; attempts < 100; attempts++) {
19
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
19
20
  const tmpPoint = {
20
- x: center.x + getRandom() * size.width - size.width / 2,
21
- y: center.y + getRandom() * size.height - size.height / 2,
21
+ x: center.x + getRandom() * size.width - size.width * half,
22
+ y: center.y + getRandom() * size.height - size.height * half,
22
23
  };
23
24
  if (ctx.isPointInStroke(path, tmpPoint.x, tmpPoint.y)) {
24
25
  randomPoint = tmpPoint;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/plugin-emitters-shape-path",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "tsParticles emitters shape path plugin",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -100,8 +100,8 @@
100
100
  "./package.json": "./package.json"
101
101
  },
102
102
  "dependencies": {
103
- "@tsparticles/engine": "^3.0.2",
104
- "@tsparticles/plugin-emitters": "^3.0.2"
103
+ "@tsparticles/engine": "^3.1.0",
104
+ "@tsparticles/plugin-emitters": "^3.1.0"
105
105
  },
106
106
  "publishConfig": {
107
107
  "access": "public"
package/report.html CHANGED
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8"/>
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
6
- <title>@tsparticles/plugin-emitters-shape-path [6 Dec 2023 at 17:48]</title>
6
+ <title>@tsparticles/plugin-emitters-shape-path [13 Jan 2024 at 23:10]</title>
7
7
  <link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" />
8
8
 
9
9
  <script>
@@ -31,7 +31,7 @@
31
31
  <body>
32
32
  <div id="app"></div>
33
33
  <script>
34
- window.chartData = [{"label":"tsparticles.plugin.emitters.shape.path.js","isAsset":true,"statSize":4542,"parsedSize":8718,"gzipSize":2316,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":4458,"groups":[{"id":115,"label":"index.js + 4 modules (concatenated)","path":"./dist/browser/index.js + 4 modules (concatenated)","statSize":4458,"parsedSize":8718,"gzipSize":2316,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser","statSize":4458,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/index.js","statSize":351,"parsedSize":686,"gzipSize":182,"inaccurateSizes":true},{"id":null,"label":"EmittersPathShapeGenerator.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/EmittersPathShapeGenerator.js","statSize":400,"parsedSize":782,"gzipSize":207,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/Options/Classes","statSize":282,"groups":[{"id":null,"label":"EmittersPathShapeOptions.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/Options/Classes/EmittersPathShapeOptions.js","statSize":282,"parsedSize":551,"gzipSize":146,"inaccurateSizes":true}],"parsedSize":551,"gzipSize":146,"inaccurateSizes":true},{"id":null,"label":"EmittersPathShape.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/EmittersPathShape.js","statSize":2476,"parsedSize":4842,"gzipSize":1286,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/utils.js","statSize":949,"parsedSize":1855,"gzipSize":493,"inaccurateSizes":true}],"parsedSize":8718,"gzipSize":2316,"inaccurateSizes":true}]}],"parsedSize":8718,"gzipSize":2316},{"label":"engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":533,"label":"engine\",\"root\":\"window\"}","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles/engine\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0},{"label":"plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles","path":"./plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":68,"label":"plugin-emitters\",\"root\":\"window\"}","path":"./plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles/plugin-emitters\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.plugin.emitters.shape.path":true}}];
34
+ window.chartData = [{"label":"tsparticles.plugin.emitters.shape.path.js","isAsset":true,"statSize":4973,"parsedSize":9379,"gzipSize":2428,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":4889,"groups":[{"id":627,"label":"index.js + 4 modules (concatenated)","path":"./dist/browser/index.js + 4 modules (concatenated)","statSize":4889,"parsedSize":9379,"gzipSize":2428,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser","statSize":4889,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/index.js","statSize":310,"parsedSize":594,"gzipSize":153,"inaccurateSizes":true},{"id":null,"label":"EmittersPathShapeGenerator.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/EmittersPathShapeGenerator.js","statSize":400,"parsedSize":767,"gzipSize":198,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/Options/Classes","statSize":358,"groups":[{"id":null,"label":"EmittersPathShapeOptions.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/Options/Classes/EmittersPathShapeOptions.js","statSize":358,"parsedSize":686,"gzipSize":177,"inaccurateSizes":true}],"parsedSize":686,"gzipSize":177,"inaccurateSizes":true},{"id":null,"label":"EmittersPathShape.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/EmittersPathShape.js","statSize":2805,"parsedSize":5381,"gzipSize":1393,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 4 modules (concatenated)/dist/browser/utils.js","statSize":1016,"parsedSize":1949,"gzipSize":504,"inaccurateSizes":true}],"parsedSize":9379,"gzipSize":2428,"inaccurateSizes":true}]}],"parsedSize":9379,"gzipSize":2428},{"label":"engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":533,"label":"engine\",\"root\":\"window\"}","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles/engine\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0},{"label":"plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles","path":"./plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":68,"label":"plugin-emitters\",\"root\":\"window\"}","path":"./plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles/plugin-emitters\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.plugin.emitters.shape.path":true}}];
35
35
  window.entrypoints = ["tsparticles.plugin.emitters.shape.path","tsparticles.plugin.emitters.shape.path.min"];
36
36
  window.defaultSizes = "parsed";
37
37
  </script>
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v3.0.2
7
+ * v3.1.0
8
8
  */
9
9
  (function webpackUniversalModuleDefinition(root, factory) {
10
10
  if(typeof exports === 'object' && typeof module === 'object')
@@ -107,12 +107,14 @@ var plugin_emitters_root_window_ = __webpack_require__(68);
107
107
  var engine_root_window_ = __webpack_require__(533);
108
108
  ;// CONCATENATED MODULE: ./dist/browser/utils.js
109
109
 
110
+ const maxAttempts = 100,
111
+ half = 0.5;
110
112
  function generateRandomPointWithinPath(ctx, path, center, size) {
111
113
  let randomPoint = null;
112
- for (let attempts = 0; attempts < 100; attempts++) {
114
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
113
115
  const tmpPoint = {
114
- x: center.x + (0,engine_root_window_.getRandom)() * size.width - size.width / 2,
115
- y: center.y + (0,engine_root_window_.getRandom)() * size.height - size.height / 2
116
+ x: center.x + (0,engine_root_window_.getRandom)() * size.width - size.width * half,
117
+ y: center.y + (0,engine_root_window_.getRandom)() * size.height - size.height * half
116
118
  };
117
119
  if (ctx.isPointInPath(path, tmpPoint.x, tmpPoint.y)) {
118
120
  randomPoint = tmpPoint;
@@ -123,10 +125,10 @@ function generateRandomPointWithinPath(ctx, path, center, size) {
123
125
  }
124
126
  function generateRandomPointOnPathPerimeter(ctx, path, center, size) {
125
127
  let randomPoint = null;
126
- for (let attempts = 0; attempts < 100; attempts++) {
128
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
127
129
  const tmpPoint = {
128
- x: center.x + (0,engine_root_window_.getRandom)() * size.width - size.width / 2,
129
- y: center.y + (0,engine_root_window_.getRandom)() * size.height - size.height / 2
130
+ x: center.x + (0,engine_root_window_.getRandom)() * size.width - size.width * half,
131
+ y: center.y + (0,engine_root_window_.getRandom)() * size.height - size.height * half
130
132
  };
131
133
  if (ctx.isPointInStroke(path, tmpPoint.x, tmpPoint.y)) {
132
134
  randomPoint = tmpPoint;
@@ -139,6 +141,7 @@ function generateRandomPointOnPathPerimeter(ctx, path, center, size) {
139
141
 
140
142
 
141
143
 
144
+ const EmittersPathShape_half = 0.5;
142
145
  class EmittersPathShape extends plugin_emitters_root_window_.EmitterShapeBase {
143
146
  constructor(position, size, fill, options) {
144
147
  super(position, size, fill, options);
@@ -151,24 +154,26 @@ class EmittersPathShape extends plugin_emitters_root_window_.EmitterShapeBase {
151
154
  const pathData = this.points,
152
155
  path = new Path2D(),
153
156
  offset = {
154
- x: position.x - size.width / 2,
155
- y: position.y - size.height / 2
157
+ x: position.x - size.width * EmittersPathShape_half,
158
+ y: position.y - size.height * EmittersPathShape_half
156
159
  };
157
160
  for (const [index, point] of pathData.entries()) {
158
161
  const coords = {
159
- x: offset.x + point.x * size.width / 100,
160
- y: offset.y + point.y * size.height / 100
162
+ x: offset.x + point.x * size.width / engine_root_window_.percentDenominator,
163
+ y: offset.y + point.y * size.height / engine_root_window_.percentDenominator
161
164
  };
162
- if (index === 0) {
165
+ if (!index) {
163
166
  path.moveTo(coords.x, coords.y);
164
167
  } else {
165
168
  path.lineTo(coords.x, coords.y);
166
169
  }
167
170
  }
168
- if (pathData[0]) {
171
+ const firstIndex = 0,
172
+ firstPathData = pathData[firstIndex];
173
+ if (firstPathData) {
169
174
  const coords = {
170
- x: offset.x + pathData[0].x * size.width / 100,
171
- y: offset.y + pathData[0].y * size.height / 100
175
+ x: offset.x + firstPathData.x * size.width / engine_root_window_.percentDenominator,
176
+ y: offset.y + firstPathData.y * size.height / engine_root_window_.percentDenominator
172
177
  };
173
178
  path.lineTo(coords.x, coords.y);
174
179
  }
@@ -182,33 +187,35 @@ class EmittersPathShape extends plugin_emitters_root_window_.EmitterShapeBase {
182
187
  fill = this.fill,
183
188
  path = this.path,
184
189
  res = fill ? generateRandomPointWithinPath(ctx, path, position, size) : generateRandomPointOnPathPerimeter(ctx, path, position, size);
185
- return res ? {
190
+ return Promise.resolve(res ? {
186
191
  position: res
187
- } : null;
192
+ } : null);
188
193
  }
189
194
  resize(position, size) {
190
195
  super.resize(position, size);
191
196
  const pathData = this.points,
192
197
  path = new Path2D(),
193
198
  offset = {
194
- x: position.x - size.width / 2,
195
- y: position.y - size.height / 2
199
+ x: position.x - size.width * EmittersPathShape_half,
200
+ y: position.y - size.height * EmittersPathShape_half
196
201
  };
197
202
  for (const [index, point] of pathData.entries()) {
198
203
  const coords = {
199
- x: offset.x + point.x * size.width / 100,
200
- y: offset.y + point.y * size.height / 100
204
+ x: offset.x + point.x * size.width / engine_root_window_.percentDenominator,
205
+ y: offset.y + point.y * size.height / engine_root_window_.percentDenominator
201
206
  };
202
- if (index === 0) {
207
+ if (!index) {
203
208
  path.moveTo(coords.x, coords.y);
204
209
  } else {
205
210
  path.lineTo(coords.x, coords.y);
206
211
  }
207
212
  }
208
- if (pathData[0]) {
213
+ const firstIndex = 0,
214
+ firstPathData = pathData[firstIndex];
215
+ if (firstPathData) {
209
216
  const coords = {
210
- x: offset.x + pathData[0].x * size.width / 100,
211
- y: offset.y + pathData[0].y * size.height / 100
217
+ x: offset.x + firstPathData.x * size.width / engine_root_window_.percentDenominator,
218
+ y: offset.y + firstPathData.y * size.height / engine_root_window_.percentDenominator
212
219
  };
213
220
  path.lineTo(coords.x, coords.y);
214
221
  }
@@ -216,6 +223,10 @@ class EmittersPathShape extends plugin_emitters_root_window_.EmitterShapeBase {
216
223
  }
217
224
  }
218
225
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/EmittersPathShapeOptions.js
226
+ const defaultPosition = {
227
+ x: 50,
228
+ y: 50
229
+ };
219
230
  class EmittersPathShapeOptions {
220
231
  constructor() {
221
232
  this.points = [];
@@ -226,8 +237,8 @@ class EmittersPathShapeOptions {
226
237
  }
227
238
  if (data.points !== undefined) {
228
239
  this.points = data.points.map(t => ({
229
- x: t.x ?? 50,
230
- y: t.y ?? 50
240
+ x: t.x ?? defaultPosition.x,
241
+ y: t.y ?? defaultPosition.y
231
242
  }));
232
243
  }
233
244
  }
@@ -246,7 +257,7 @@ class EmittersPathShapeGenerator {
246
257
 
247
258
  async function loadEmittersShapePath(engine, refresh = true) {
248
259
  const emittersEngine = engine;
249
- emittersEngine.addEmitterShapeGenerator && emittersEngine.addEmitterShapeGenerator("path", new EmittersPathShapeGenerator());
260
+ emittersEngine.addEmitterShapeGenerator?.("path", new EmittersPathShapeGenerator());
250
261
  await emittersEngine.refresh(refresh);
251
262
  }
252
263
  })();
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see tsparticles.plugin.emitters.shape.path.min.js.LICENSE.txt */
2
- !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/plugin-emitters","@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine")):e(t.window,t.window);for(var o in i)("object"==typeof exports?exports:t)[o]=i[o]}}(this,((t,e)=>(()=>{"use strict";var i={533:t=>{t.exports=e},68:e=>{e.exports=t}},o={};function n(t){var e=o[t];if(void 0!==e)return e.exports;var r=o[t]={exports:{}};return i[t](r,r.exports,n),r.exports}n.d=(t,e)=>{for(var i in e)n.o(e,i)&&!n.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),n.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var r={};return(()=>{n.r(r),n.d(r,{loadEmittersShapePath:()=>a});var t=n(68),e=n(533);class i extends t.EmitterShapeBase{constructor(t,i,o,n){super(t,i,o,n);const r=document.createElement("canvas").getContext("2d");if(!r)throw new Error(`${e.errorPrefix} No 2d context available`);this.checkContext=r,this.points=n.points;const s=this.points,a=new Path2D,h=t.x-i.width/2,c=t.y-i.height/2;for(const[t,e]of s.entries()){const o={x:h+e.x*i.width/100,y:c+e.y*i.height/100};0===t?a.moveTo(o.x,o.y):a.lineTo(o.x,o.y)}if(s[0]){const t={x:h+s[0].x*i.width/100,y:c+s[0].y*i.height/100};a.lineTo(t.x,t.y)}this.path=a}async init(){}async randomPosition(){const t=this.checkContext,i=this.position,o=this.size,n=this.fill,r=this.path,s=n?function(t,i,o,n){let r=null;for(let s=0;s<100;s++){const s={x:o.x+(0,e.getRandom)()*n.width-n.width/2,y:o.y+(0,e.getRandom)()*n.height-n.height/2};if(t.isPointInPath(i,s.x,s.y)){r=s;break}}return r}(t,r,i,o):function(t,i,o,n){let r=null;for(let s=0;s<100;s++){const s={x:o.x+(0,e.getRandom)()*n.width-n.width/2,y:o.y+(0,e.getRandom)()*n.height-n.height/2};if(t.isPointInStroke(i,s.x,s.y)){r=s;break}}return r}(t,r,i,o);return s?{position:s}:null}resize(t,e){super.resize(t,e);const i=this.points,o=new Path2D,n=t.x-e.width/2,r=t.y-e.height/2;for(const[t,s]of i.entries()){const i={x:n+s.x*e.width/100,y:r+s.y*e.height/100};0===t?o.moveTo(i.x,i.y):o.lineTo(i.x,i.y)}if(i[0]){const t={x:n+i[0].x*e.width/100,y:r+i[0].y*e.height/100};o.lineTo(t.x,t.y)}this.path=o}}class o{constructor(){this.points=[]}load(t){t&&void 0!==t.points&&(this.points=t.points.map((t=>({x:t.x??50,y:t.y??50}))))}}class s{generate(t,e,n,r){const s=new o;return s.load(r),new i(t,e,n,s)}}async function a(t,e=!0){const i=t;i.addEmitterShapeGenerator&&i.addEmitterShapeGenerator("path",new s),await i.refresh(e)}})(),r})()));
2
+ !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/plugin-emitters","@tsparticles/engine"],e);else{var o="object"==typeof exports?e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine")):e(t.window,t.window);for(var n in o)("object"==typeof exports?exports:t)[n]=o[n]}}(this,((t,e)=>(()=>{"use strict";var o={533:t=>{t.exports=e},68:e=>{e.exports=t}},n={};function i(t){var e=n[t];if(void 0!==e)return e.exports;var r=n[t]={exports:{}};return o[t](r,r.exports,i),r.exports}i.d=(t,e)=>{for(var o in e)i.o(e,o)&&!i.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var r={};return(()=>{i.r(r),i.d(r,{loadEmittersShapePath:()=>l});var t=i(68),e=i(533);const o=.5;const n=.5;class s extends t.EmitterShapeBase{constructor(t,o,i,r){super(t,o,i,r);const s=document.createElement("canvas").getContext("2d");if(!s)throw new Error(`${e.errorPrefix} No 2d context available`);this.checkContext=s,this.points=r.points;const a=this.points,c=new Path2D,h=t.x-o.width*n,p=t.y-o.height*n;for(const[t,n]of a.entries()){const i={x:h+n.x*o.width/e.percentDenominator,y:p+n.y*o.height/e.percentDenominator};t?c.lineTo(i.x,i.y):c.moveTo(i.x,i.y)}const l=a[0];if(l){const t={x:h+l.x*o.width/e.percentDenominator,y:p+l.y*o.height/e.percentDenominator};c.lineTo(t.x,t.y)}this.path=c}async init(){}async randomPosition(){const t=this.checkContext,n=this.position,i=this.size,r=this.fill,s=this.path,a=r?function(t,n,i,r){let s=null;for(let a=0;a<100;a++){const a={x:i.x+(0,e.getRandom)()*r.width-r.width*o,y:i.y+(0,e.getRandom)()*r.height-r.height*o};if(t.isPointInPath(n,a.x,a.y)){s=a;break}}return s}(t,s,n,i):function(t,n,i,r){let s=null;for(let a=0;a<100;a++){const a={x:i.x+(0,e.getRandom)()*r.width-r.width*o,y:i.y+(0,e.getRandom)()*r.height-r.height*o};if(t.isPointInStroke(n,a.x,a.y)){s=a;break}}return s}(t,s,n,i);return Promise.resolve(a?{position:a}:null)}resize(t,o){super.resize(t,o);const i=this.points,r=new Path2D,s=t.x-o.width*n,a=t.y-o.height*n;for(const[t,n]of i.entries()){const i={x:s+n.x*o.width/e.percentDenominator,y:a+n.y*o.height/e.percentDenominator};t?r.lineTo(i.x,i.y):r.moveTo(i.x,i.y)}const c=i[0];if(c){const t={x:s+c.x*o.width/e.percentDenominator,y:a+c.y*o.height/e.percentDenominator};r.lineTo(t.x,t.y)}this.path=r}}const a=50,c=50;class h{constructor(){this.points=[]}load(t){t&&void 0!==t.points&&(this.points=t.points.map((t=>({x:t.x??a,y:t.y??c}))))}}class p{generate(t,e,o,n){const i=new h;return i.load(n),new s(t,e,o,i)}}async function l(t,e=!0){const o=t;o.addEmitterShapeGenerator?.("path",new p),await o.refresh(e)}})(),r})()));
@@ -1 +1 @@
1
- /*! tsParticles Emitters Shape Path Plugin v3.0.2 by Matteo Bruni */
1
+ /*! tsParticles Emitters Shape Path Plugin v3.1.0 by Matteo Bruni */
@@ -13,6 +13,7 @@
13
13
  const plugin_emitters_1 = require("@tsparticles/plugin-emitters");
14
14
  const engine_1 = require("@tsparticles/engine");
15
15
  const utils_js_1 = require("./utils.js");
16
+ const half = 0.5;
16
17
  class EmittersPathShape extends plugin_emitters_1.EmitterShapeBase {
17
18
  constructor(position, size, fill, options) {
18
19
  super(position, size, fill, options);
@@ -23,25 +24,26 @@
23
24
  this.checkContext = ctx;
24
25
  this.points = options.points;
25
26
  const pathData = this.points, path = new Path2D(), offset = {
26
- x: position.x - size.width / 2,
27
- y: position.y - size.height / 2,
27
+ x: position.x - size.width * half,
28
+ y: position.y - size.height * half,
28
29
  };
29
30
  for (const [index, point] of pathData.entries()) {
30
31
  const coords = {
31
- x: offset.x + (point.x * size.width) / 100,
32
- y: offset.y + (point.y * size.height) / 100,
32
+ x: offset.x + (point.x * size.width) / engine_1.percentDenominator,
33
+ y: offset.y + (point.y * size.height) / engine_1.percentDenominator,
33
34
  };
34
- if (index === 0) {
35
+ if (!index) {
35
36
  path.moveTo(coords.x, coords.y);
36
37
  }
37
38
  else {
38
39
  path.lineTo(coords.x, coords.y);
39
40
  }
40
41
  }
41
- if (pathData[0]) {
42
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
43
+ if (firstPathData) {
42
44
  const coords = {
43
- x: offset.x + (pathData[0].x * size.width) / 100,
44
- y: offset.y + (pathData[0].y * size.height) / 100,
45
+ x: offset.x + (firstPathData.x * size.width) / engine_1.percentDenominator,
46
+ y: offset.y + (firstPathData.y * size.height) / engine_1.percentDenominator,
45
47
  };
46
48
  path.lineTo(coords.x, coords.y);
47
49
  }
@@ -53,30 +55,31 @@
53
55
  const ctx = this.checkContext, position = this.position, size = this.size, fill = this.fill, path = this.path, res = fill
54
56
  ? (0, utils_js_1.generateRandomPointWithinPath)(ctx, path, position, size)
55
57
  : (0, utils_js_1.generateRandomPointOnPathPerimeter)(ctx, path, position, size);
56
- return res ? { position: res } : null;
58
+ return Promise.resolve(res ? { position: res } : null);
57
59
  }
58
60
  resize(position, size) {
59
61
  super.resize(position, size);
60
62
  const pathData = this.points, path = new Path2D(), offset = {
61
- x: position.x - size.width / 2,
62
- y: position.y - size.height / 2,
63
+ x: position.x - size.width * half,
64
+ y: position.y - size.height * half,
63
65
  };
64
66
  for (const [index, point] of pathData.entries()) {
65
67
  const coords = {
66
- x: offset.x + (point.x * size.width) / 100,
67
- y: offset.y + (point.y * size.height) / 100,
68
+ x: offset.x + (point.x * size.width) / engine_1.percentDenominator,
69
+ y: offset.y + (point.y * size.height) / engine_1.percentDenominator,
68
70
  };
69
- if (index === 0) {
71
+ if (!index) {
70
72
  path.moveTo(coords.x, coords.y);
71
73
  }
72
74
  else {
73
75
  path.lineTo(coords.x, coords.y);
74
76
  }
75
77
  }
76
- if (pathData[0]) {
78
+ const firstIndex = 0, firstPathData = pathData[firstIndex];
79
+ if (firstPathData) {
77
80
  const coords = {
78
- x: offset.x + (pathData[0].x * size.width) / 100,
79
- y: offset.y + (pathData[0].y * size.height) / 100,
81
+ x: offset.x + (firstPathData.x * size.width) / engine_1.percentDenominator,
82
+ y: offset.y + (firstPathData.y * size.height) / engine_1.percentDenominator,
80
83
  };
81
84
  path.lineTo(coords.x, coords.y);
82
85
  }
@@ -10,6 +10,7 @@
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.EmittersPathShapeOptions = void 0;
13
+ const defaultPosition = { x: 50, y: 50 };
13
14
  class EmittersPathShapeOptions {
14
15
  constructor() {
15
16
  this.points = [];
@@ -19,7 +20,7 @@
19
20
  return;
20
21
  }
21
22
  if (data.points !== undefined) {
22
- this.points = data.points.map((t) => ({ x: t.x ?? 50, y: t.y ?? 50 }));
23
+ this.points = data.points.map((t) => ({ x: t.x ?? defaultPosition.x, y: t.y ?? defaultPosition.y }));
23
24
  }
24
25
  }
25
26
  }
package/umd/index.js CHANGED
@@ -13,8 +13,7 @@
13
13
  const EmittersPathShapeGenerator_js_1 = require("./EmittersPathShapeGenerator.js");
14
14
  async function loadEmittersShapePath(engine, refresh = true) {
15
15
  const emittersEngine = engine;
16
- emittersEngine.addEmitterShapeGenerator &&
17
- emittersEngine.addEmitterShapeGenerator("path", new EmittersPathShapeGenerator_js_1.EmittersPathShapeGenerator());
16
+ emittersEngine.addEmitterShapeGenerator?.("path", new EmittersPathShapeGenerator_js_1.EmittersPathShapeGenerator());
18
17
  await emittersEngine.refresh(refresh);
19
18
  }
20
19
  exports.loadEmittersShapePath = loadEmittersShapePath;
package/umd/utils.js CHANGED
@@ -11,12 +11,13 @@
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.generateRandomPointOnPathPerimeter = exports.generateRandomPointWithinPath = void 0;
13
13
  const engine_1 = require("@tsparticles/engine");
14
+ const maxAttempts = 100, half = 0.5;
14
15
  function generateRandomPointWithinPath(ctx, path, center, size) {
15
16
  let randomPoint = null;
16
- for (let attempts = 0; attempts < 100; attempts++) {
17
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
17
18
  const tmpPoint = {
18
- x: center.x + (0, engine_1.getRandom)() * size.width - size.width / 2,
19
- y: center.y + (0, engine_1.getRandom)() * size.height - size.height / 2,
19
+ x: center.x + (0, engine_1.getRandom)() * size.width - size.width * half,
20
+ y: center.y + (0, engine_1.getRandom)() * size.height - size.height * half,
20
21
  };
21
22
  if (ctx.isPointInPath(path, tmpPoint.x, tmpPoint.y)) {
22
23
  randomPoint = tmpPoint;
@@ -28,10 +29,10 @@
28
29
  exports.generateRandomPointWithinPath = generateRandomPointWithinPath;
29
30
  function generateRandomPointOnPathPerimeter(ctx, path, center, size) {
30
31
  let randomPoint = null;
31
- for (let attempts = 0; attempts < 100; attempts++) {
32
+ for (let attempts = 0; attempts < maxAttempts; attempts++) {
32
33
  const tmpPoint = {
33
- x: center.x + (0, engine_1.getRandom)() * size.width - size.width / 2,
34
- y: center.y + (0, engine_1.getRandom)() * size.height - size.height / 2,
34
+ x: center.x + (0, engine_1.getRandom)() * size.width - size.width * half,
35
+ y: center.y + (0, engine_1.getRandom)() * size.height - size.height * half,
35
36
  };
36
37
  if (ctx.isPointInStroke(path, tmpPoint.x, tmpPoint.y)) {
37
38
  randomPoint = tmpPoint;