@tsparticles/plugin-emitters-shape-canvas 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,11 +1,12 @@
1
1
  import { EmitterShapeBase } from "@tsparticles/plugin-emitters";
2
2
  import { getRandom, isFunction, isString } from "@tsparticles/engine";
3
3
  import { getCanvasImageData, getImageData, getTextData } from "./utils.js";
4
+ const maxRetries = 100, half = 0.5;
4
5
  export class EmittersCanvasShape extends EmitterShapeBase {
5
6
  constructor(position, size, fill, options) {
6
7
  super(position, size, fill, options);
7
- const filter = options.filter;
8
- let filterFunc = (pixel) => pixel.a > 0;
8
+ const filter = options.filter, minAlpha = 0;
9
+ let filterFunc = (pixel) => pixel.a > minAlpha;
9
10
  if (filter !== undefined) {
10
11
  if (isString(filter)) {
11
12
  if (Object.hasOwn(window, filter)) {
@@ -44,8 +45,8 @@ export class EmittersCanvasShape extends EmitterShapeBase {
44
45
  }
45
46
  pixelData = data;
46
47
  }
47
- else if (element || selector) {
48
- const canvas = element || (selector && document.querySelector(selector));
48
+ else if (element ?? selector) {
49
+ const canvas = element ?? (selector && document.querySelector(selector));
49
50
  if (!canvas) {
50
51
  return;
51
52
  }
@@ -61,12 +62,11 @@ export class EmittersCanvasShape extends EmitterShapeBase {
61
62
  this.pixelData = pixelData;
62
63
  }
63
64
  async randomPosition() {
64
- const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale;
65
- const positionOffset = {
66
- x: position.x - (width * scale) / 2,
67
- y: position.y - (height * scale) / 2,
65
+ const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
66
+ x: position.x - width * scale * half,
67
+ y: position.y - height * scale * half,
68
68
  };
69
- for (let i = 0; i < 100; i++) {
69
+ for (let i = 0; i < maxRetries; i++) {
70
70
  const nextIndex = Math.floor(getRandom() * width * height), pixelPos = {
71
71
  x: nextIndex % width,
72
72
  y: Math.floor(nextIndex / width),
@@ -74,16 +74,16 @@ export class EmittersCanvasShape extends EmitterShapeBase {
74
74
  if (!shouldCreateParticle) {
75
75
  continue;
76
76
  }
77
- return {
77
+ return Promise.resolve({
78
78
  position: {
79
79
  x: pixelPos.x * scale + positionOffset.x,
80
80
  y: pixelPos.y * scale + positionOffset.y,
81
81
  },
82
82
  color: { ...pixel },
83
83
  opacity: pixel.a,
84
- };
84
+ });
85
85
  }
86
- return null;
86
+ return Promise.resolve(null);
87
87
  }
88
88
  resize(position, size) {
89
89
  super.resize(position, size);
@@ -1,8 +1,9 @@
1
1
  import { PixelsOptions } from "./PixelsOptions.js";
2
2
  import { TextOptions } from "./TextOptions.js";
3
+ const minAlpha = 0;
3
4
  export class EmittersCanvasShapeOptions {
4
5
  constructor() {
5
- this.filter = (pixel) => pixel.a > 0;
6
+ this.filter = (pixel) => pixel.a > minAlpha;
6
7
  this.pixels = new PixelsOptions();
7
8
  this.scale = 1;
8
9
  this.selector = "";
package/browser/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { EmittersCanvasShapeGenerator } from "./EmittersCanvasShapeGenerator.js";
2
2
  export async function loadEmittersShapeCanvas(engine, refresh = true) {
3
3
  const emittersEngine = engine;
4
- emittersEngine.addEmitterShapeGenerator &&
5
- emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator());
4
+ emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
6
5
  await emittersEngine.refresh(refresh);
7
6
  }
package/browser/utils.js CHANGED
@@ -1,8 +1,12 @@
1
1
  import { errorPrefix, isNumber } from "@tsparticles/engine";
2
+ const origin = {
3
+ x: 0,
4
+ y: 0,
5
+ }, minWidth = 0;
2
6
  export function getCanvasImageData(ctx, size, offset, clear = true) {
3
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
7
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
4
8
  if (clear) {
5
- ctx.clearRect(0, 0, size.width, size.height);
9
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
6
10
  }
7
11
  const pixels = [];
8
12
  for (let i = 0; i < imageData.length; i += offset) {
@@ -13,11 +17,17 @@ export function getCanvasImageData(ctx, size, offset, clear = true) {
13
17
  if (!pixels[pos.y]) {
14
18
  pixels[pos.y] = [];
15
19
  }
20
+ const indexesOffset = {
21
+ r: 0,
22
+ g: 1,
23
+ b: 2,
24
+ a: 3,
25
+ }, alphaFactor = 255;
16
26
  pixels[pos.y][pos.x] = {
17
- r: imageData[i],
18
- g: imageData[i + 1],
19
- b: imageData[i + 2],
20
- a: imageData[i + 3] / 255,
27
+ r: imageData[i + indexesOffset.r],
28
+ g: imageData[i + indexesOffset.g],
29
+ b: imageData[i + indexesOffset.b],
30
+ a: imageData[i + indexesOffset.a] / alphaFactor,
21
31
  };
22
32
  }
23
33
  return {
@@ -39,7 +49,7 @@ export function getImageData(src, offset) {
39
49
  if (!context) {
40
50
  return reject(new Error(`${errorPrefix} Could not get canvas context`));
41
51
  }
42
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
52
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
43
53
  resolve(getCanvasImageData(context, canvas, offset));
44
54
  };
45
55
  });
@@ -61,7 +71,7 @@ export function getTextData(textOptions, offset, fill) {
61
71
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
62
72
  width: measure.width,
63
73
  };
64
- maxWidth = Math.max(maxWidth || 0, lineData.width);
74
+ maxWidth = Math.max(maxWidth || minWidth, lineData.width);
65
75
  totalHeight += lineData.height + linesOptions.spacing;
66
76
  linesData.push(lineData);
67
77
  }
@@ -72,11 +82,11 @@ export function getTextData(textOptions, offset, fill) {
72
82
  context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
73
83
  if (fill) {
74
84
  context.fillStyle = color;
75
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
85
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
76
86
  }
77
87
  else {
78
88
  context.strokeStyle = color;
79
- context.strokeText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
89
+ context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
80
90
  }
81
91
  currentHeight += line.height + linesOptions.spacing;
82
92
  }
@@ -4,11 +4,12 @@ exports.EmittersCanvasShape = 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 maxRetries = 100, half = 0.5;
7
8
  class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
8
9
  constructor(position, size, fill, options) {
9
10
  super(position, size, fill, options);
10
- const filter = options.filter;
11
- let filterFunc = (pixel) => pixel.a > 0;
11
+ const filter = options.filter, minAlpha = 0;
12
+ let filterFunc = (pixel) => pixel.a > minAlpha;
12
13
  if (filter !== undefined) {
13
14
  if ((0, engine_1.isString)(filter)) {
14
15
  if (Object.hasOwn(window, filter)) {
@@ -47,8 +48,8 @@ class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
47
48
  }
48
49
  pixelData = data;
49
50
  }
50
- else if (element || selector) {
51
- const canvas = element || (selector && document.querySelector(selector));
51
+ else if (element ?? selector) {
52
+ const canvas = element ?? (selector && document.querySelector(selector));
52
53
  if (!canvas) {
53
54
  return;
54
55
  }
@@ -64,12 +65,11 @@ class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
64
65
  this.pixelData = pixelData;
65
66
  }
66
67
  async randomPosition() {
67
- const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale;
68
- const positionOffset = {
69
- x: position.x - (width * scale) / 2,
70
- y: position.y - (height * scale) / 2,
68
+ const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
69
+ x: position.x - width * scale * half,
70
+ y: position.y - height * scale * half,
71
71
  };
72
- for (let i = 0; i < 100; i++) {
72
+ for (let i = 0; i < maxRetries; i++) {
73
73
  const nextIndex = Math.floor((0, engine_1.getRandom)() * width * height), pixelPos = {
74
74
  x: nextIndex % width,
75
75
  y: Math.floor(nextIndex / width),
@@ -77,16 +77,16 @@ class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
77
77
  if (!shouldCreateParticle) {
78
78
  continue;
79
79
  }
80
- return {
80
+ return Promise.resolve({
81
81
  position: {
82
82
  x: pixelPos.x * scale + positionOffset.x,
83
83
  y: pixelPos.y * scale + positionOffset.y,
84
84
  },
85
85
  color: { ...pixel },
86
86
  opacity: pixel.a,
87
- };
87
+ });
88
88
  }
89
- return null;
89
+ return Promise.resolve(null);
90
90
  }
91
91
  resize(position, size) {
92
92
  super.resize(position, size);
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EmittersCanvasShapeOptions = void 0;
4
4
  const PixelsOptions_js_1 = require("./PixelsOptions.js");
5
5
  const TextOptions_js_1 = require("./TextOptions.js");
6
+ const minAlpha = 0;
6
7
  class EmittersCanvasShapeOptions {
7
8
  constructor() {
8
- this.filter = (pixel) => pixel.a > 0;
9
+ this.filter = (pixel) => pixel.a > minAlpha;
9
10
  this.pixels = new PixelsOptions_js_1.PixelsOptions();
10
11
  this.scale = 1;
11
12
  this.selector = "";
package/cjs/index.js CHANGED
@@ -4,8 +4,7 @@ exports.loadEmittersShapeCanvas = void 0;
4
4
  const EmittersCanvasShapeGenerator_js_1 = require("./EmittersCanvasShapeGenerator.js");
5
5
  async function loadEmittersShapeCanvas(engine, refresh = true) {
6
6
  const emittersEngine = engine;
7
- emittersEngine.addEmitterShapeGenerator &&
8
- emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
7
+ emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
9
8
  await emittersEngine.refresh(refresh);
10
9
  }
11
10
  exports.loadEmittersShapeCanvas = loadEmittersShapeCanvas;
package/cjs/utils.js CHANGED
@@ -2,10 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTextData = exports.getImageData = exports.getCanvasImageData = void 0;
4
4
  const engine_1 = require("@tsparticles/engine");
5
+ const origin = {
6
+ x: 0,
7
+ y: 0,
8
+ }, minWidth = 0;
5
9
  function getCanvasImageData(ctx, size, offset, clear = true) {
6
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
10
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
7
11
  if (clear) {
8
- ctx.clearRect(0, 0, size.width, size.height);
12
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
9
13
  }
10
14
  const pixels = [];
11
15
  for (let i = 0; i < imageData.length; i += offset) {
@@ -16,11 +20,17 @@ function getCanvasImageData(ctx, size, offset, clear = true) {
16
20
  if (!pixels[pos.y]) {
17
21
  pixels[pos.y] = [];
18
22
  }
23
+ const indexesOffset = {
24
+ r: 0,
25
+ g: 1,
26
+ b: 2,
27
+ a: 3,
28
+ }, alphaFactor = 255;
19
29
  pixels[pos.y][pos.x] = {
20
- r: imageData[i],
21
- g: imageData[i + 1],
22
- b: imageData[i + 2],
23
- a: imageData[i + 3] / 255,
30
+ r: imageData[i + indexesOffset.r],
31
+ g: imageData[i + indexesOffset.g],
32
+ b: imageData[i + indexesOffset.b],
33
+ a: imageData[i + indexesOffset.a] / alphaFactor,
24
34
  };
25
35
  }
26
36
  return {
@@ -43,7 +53,7 @@ function getImageData(src, offset) {
43
53
  if (!context) {
44
54
  return reject(new Error(`${engine_1.errorPrefix} Could not get canvas context`));
45
55
  }
46
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
56
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
47
57
  resolve(getCanvasImageData(context, canvas, offset));
48
58
  };
49
59
  });
@@ -66,7 +76,7 @@ function getTextData(textOptions, offset, fill) {
66
76
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
67
77
  width: measure.width,
68
78
  };
69
- maxWidth = Math.max(maxWidth || 0, lineData.width);
79
+ maxWidth = Math.max(maxWidth || minWidth, lineData.width);
70
80
  totalHeight += lineData.height + linesOptions.spacing;
71
81
  linesData.push(lineData);
72
82
  }
@@ -77,11 +87,11 @@ function getTextData(textOptions, offset, fill) {
77
87
  context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
78
88
  if (fill) {
79
89
  context.fillStyle = color;
80
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
90
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
81
91
  }
82
92
  else {
83
93
  context.strokeStyle = color;
84
- context.strokeText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
94
+ context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
85
95
  }
86
96
  currentHeight += line.height + linesOptions.spacing;
87
97
  }
@@ -1,11 +1,12 @@
1
1
  import { EmitterShapeBase } from "@tsparticles/plugin-emitters";
2
2
  import { getRandom, isFunction, isString } from "@tsparticles/engine";
3
3
  import { getCanvasImageData, getImageData, getTextData } from "./utils.js";
4
+ const maxRetries = 100, half = 0.5;
4
5
  export class EmittersCanvasShape extends EmitterShapeBase {
5
6
  constructor(position, size, fill, options) {
6
7
  super(position, size, fill, options);
7
- const filter = options.filter;
8
- let filterFunc = (pixel) => pixel.a > 0;
8
+ const filter = options.filter, minAlpha = 0;
9
+ let filterFunc = (pixel) => pixel.a > minAlpha;
9
10
  if (filter !== undefined) {
10
11
  if (isString(filter)) {
11
12
  if (Object.hasOwn(window, filter)) {
@@ -44,8 +45,8 @@ export class EmittersCanvasShape extends EmitterShapeBase {
44
45
  }
45
46
  pixelData = data;
46
47
  }
47
- else if (element || selector) {
48
- const canvas = element || (selector && document.querySelector(selector));
48
+ else if (element ?? selector) {
49
+ const canvas = element ?? (selector && document.querySelector(selector));
49
50
  if (!canvas) {
50
51
  return;
51
52
  }
@@ -61,12 +62,11 @@ export class EmittersCanvasShape extends EmitterShapeBase {
61
62
  this.pixelData = pixelData;
62
63
  }
63
64
  async randomPosition() {
64
- const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale;
65
- const positionOffset = {
66
- x: position.x - (width * scale) / 2,
67
- y: position.y - (height * scale) / 2,
65
+ const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
66
+ x: position.x - width * scale * half,
67
+ y: position.y - height * scale * half,
68
68
  };
69
- for (let i = 0; i < 100; i++) {
69
+ for (let i = 0; i < maxRetries; i++) {
70
70
  const nextIndex = Math.floor(getRandom() * width * height), pixelPos = {
71
71
  x: nextIndex % width,
72
72
  y: Math.floor(nextIndex / width),
@@ -74,16 +74,16 @@ export class EmittersCanvasShape extends EmitterShapeBase {
74
74
  if (!shouldCreateParticle) {
75
75
  continue;
76
76
  }
77
- return {
77
+ return Promise.resolve({
78
78
  position: {
79
79
  x: pixelPos.x * scale + positionOffset.x,
80
80
  y: pixelPos.y * scale + positionOffset.y,
81
81
  },
82
82
  color: { ...pixel },
83
83
  opacity: pixel.a,
84
- };
84
+ });
85
85
  }
86
- return null;
86
+ return Promise.resolve(null);
87
87
  }
88
88
  resize(position, size) {
89
89
  super.resize(position, size);
@@ -1,8 +1,9 @@
1
1
  import { PixelsOptions } from "./PixelsOptions.js";
2
2
  import { TextOptions } from "./TextOptions.js";
3
+ const minAlpha = 0;
3
4
  export class EmittersCanvasShapeOptions {
4
5
  constructor() {
5
- this.filter = (pixel) => pixel.a > 0;
6
+ this.filter = (pixel) => pixel.a > minAlpha;
6
7
  this.pixels = new PixelsOptions();
7
8
  this.scale = 1;
8
9
  this.selector = "";
package/esm/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { EmittersCanvasShapeGenerator } from "./EmittersCanvasShapeGenerator.js";
2
2
  export async function loadEmittersShapeCanvas(engine, refresh = true) {
3
3
  const emittersEngine = engine;
4
- emittersEngine.addEmitterShapeGenerator &&
5
- emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator());
4
+ emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
6
5
  await emittersEngine.refresh(refresh);
7
6
  }
package/esm/utils.js CHANGED
@@ -1,8 +1,12 @@
1
1
  import { errorPrefix, isNumber } from "@tsparticles/engine";
2
+ const origin = {
3
+ x: 0,
4
+ y: 0,
5
+ }, minWidth = 0;
2
6
  export function getCanvasImageData(ctx, size, offset, clear = true) {
3
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
7
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
4
8
  if (clear) {
5
- ctx.clearRect(0, 0, size.width, size.height);
9
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
6
10
  }
7
11
  const pixels = [];
8
12
  for (let i = 0; i < imageData.length; i += offset) {
@@ -13,11 +17,17 @@ export function getCanvasImageData(ctx, size, offset, clear = true) {
13
17
  if (!pixels[pos.y]) {
14
18
  pixels[pos.y] = [];
15
19
  }
20
+ const indexesOffset = {
21
+ r: 0,
22
+ g: 1,
23
+ b: 2,
24
+ a: 3,
25
+ }, alphaFactor = 255;
16
26
  pixels[pos.y][pos.x] = {
17
- r: imageData[i],
18
- g: imageData[i + 1],
19
- b: imageData[i + 2],
20
- a: imageData[i + 3] / 255,
27
+ r: imageData[i + indexesOffset.r],
28
+ g: imageData[i + indexesOffset.g],
29
+ b: imageData[i + indexesOffset.b],
30
+ a: imageData[i + indexesOffset.a] / alphaFactor,
21
31
  };
22
32
  }
23
33
  return {
@@ -39,7 +49,7 @@ export function getImageData(src, offset) {
39
49
  if (!context) {
40
50
  return reject(new Error(`${errorPrefix} Could not get canvas context`));
41
51
  }
42
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
52
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
43
53
  resolve(getCanvasImageData(context, canvas, offset));
44
54
  };
45
55
  });
@@ -61,7 +71,7 @@ export function getTextData(textOptions, offset, fill) {
61
71
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
62
72
  width: measure.width,
63
73
  };
64
- maxWidth = Math.max(maxWidth || 0, lineData.width);
74
+ maxWidth = Math.max(maxWidth || minWidth, lineData.width);
65
75
  totalHeight += lineData.height + linesOptions.spacing;
66
76
  linesData.push(lineData);
67
77
  }
@@ -72,11 +82,11 @@ export function getTextData(textOptions, offset, fill) {
72
82
  context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
73
83
  if (fill) {
74
84
  context.fillStyle = color;
75
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
85
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
76
86
  }
77
87
  else {
78
88
  context.strokeStyle = color;
79
- context.strokeText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
89
+ context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
80
90
  }
81
91
  currentHeight += line.height + linesOptions.spacing;
82
92
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/plugin-emitters-shape-canvas",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "tsParticles emitters shape canvas 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-canvas [6 Dec 2023 at 17:48]</title>
6
+ <title>@tsparticles/plugin-emitters-shape-canvas [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.canvas.js","isAsset":true,"statSize":9297,"parsedSize":13513,"gzipSize":3576,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":9213,"groups":[{"id":314,"label":"index.js + 8 modules (concatenated)","path":"./dist/browser/index.js + 8 modules (concatenated)","statSize":9213,"parsedSize":13513,"gzipSize":3576,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser","statSize":9213,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/index.js","statSize":361,"parsedSize":529,"gzipSize":140,"inaccurateSizes":true},{"id":null,"label":"EmittersCanvasShapeGenerator.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/EmittersCanvasShapeGenerator.js","statSize":414,"parsedSize":607,"gzipSize":160,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes","statSize":2511,"groups":[{"id":null,"label":"EmittersCanvasShapeOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/EmittersCanvasShapeOptions.js","statSize":828,"parsedSize":1214,"gzipSize":321,"inaccurateSizes":true},{"id":null,"label":"PixelsOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/PixelsOptions.js","statSize":205,"parsedSize":300,"gzipSize":79,"inaccurateSizes":true},{"id":null,"label":"TextOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextOptions.js","statSize":555,"parsedSize":814,"gzipSize":215,"inaccurateSizes":true},{"id":null,"label":"TextFontOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextFontOptions.js","statSize":599,"parsedSize":878,"gzipSize":232,"inaccurateSizes":true},{"id":null,"label":"TextLinesOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextLinesOptions.js","statSize":324,"parsedSize":475,"gzipSize":125,"inaccurateSizes":true}],"parsedSize":3682,"gzipSize":974,"inaccurateSizes":true},{"id":null,"label":"EmittersCanvasShape.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/EmittersCanvasShape.js","statSize":2830,"parsedSize":4150,"gzipSize":1098,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/utils.js","statSize":3097,"parsedSize":4542,"gzipSize":1202,"inaccurateSizes":true}],"parsedSize":13513,"gzipSize":3576,"inaccurateSizes":true}]}],"parsedSize":13513,"gzipSize":3576},{"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.canvas":true}}];
34
+ window.chartData = [{"label":"tsparticles.plugin.emitters.shape.canvas.js","isAsset":true,"statSize":9718,"parsedSize":13934,"gzipSize":3694,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":9634,"groups":[{"id":806,"label":"index.js + 8 modules (concatenated)","path":"./dist/browser/index.js + 8 modules (concatenated)","statSize":9634,"parsedSize":13934,"gzipSize":3694,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser","statSize":9634,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/index.js","statSize":320,"parsedSize":462,"gzipSize":122,"inaccurateSizes":true},{"id":null,"label":"EmittersCanvasShapeGenerator.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/EmittersCanvasShapeGenerator.js","statSize":414,"parsedSize":598,"gzipSize":158,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes","statSize":2538,"groups":[{"id":null,"label":"EmittersCanvasShapeOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/EmittersCanvasShapeOptions.js","statSize":855,"parsedSize":1236,"gzipSize":327,"inaccurateSizes":true},{"id":null,"label":"PixelsOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/PixelsOptions.js","statSize":205,"parsedSize":296,"gzipSize":78,"inaccurateSizes":true},{"id":null,"label":"TextOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextOptions.js","statSize":555,"parsedSize":802,"gzipSize":212,"inaccurateSizes":true},{"id":null,"label":"TextFontOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextFontOptions.js","statSize":599,"parsedSize":866,"gzipSize":229,"inaccurateSizes":true},{"id":null,"label":"TextLinesOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextLinesOptions.js","statSize":324,"parsedSize":468,"gzipSize":124,"inaccurateSizes":true}],"parsedSize":3670,"gzipSize":973,"inaccurateSizes":true},{"id":null,"label":"EmittersCanvasShape.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/EmittersCanvasShape.js","statSize":2946,"parsedSize":4260,"gzipSize":1129,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/utils.js","statSize":3416,"parsedSize":4940,"gzipSize":1309,"inaccurateSizes":true}],"parsedSize":13934,"gzipSize":3694,"inaccurateSizes":true}]}],"parsedSize":13934,"gzipSize":3694},{"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.canvas":true}}];
35
35
  window.entrypoints = ["tsparticles.plugin.emitters.shape.canvas","tsparticles.plugin.emitters.shape.canvas.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,10 +107,15 @@ 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 origin = {
111
+ x: 0,
112
+ y: 0
113
+ },
114
+ minWidth = 0;
110
115
  function getCanvasImageData(ctx, size, offset, clear = true) {
111
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
116
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
112
117
  if (clear) {
113
- ctx.clearRect(0, 0, size.width, size.height);
118
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
114
119
  }
115
120
  const pixels = [];
116
121
  for (let i = 0; i < imageData.length; i += offset) {
@@ -122,11 +127,18 @@ function getCanvasImageData(ctx, size, offset, clear = true) {
122
127
  if (!pixels[pos.y]) {
123
128
  pixels[pos.y] = [];
124
129
  }
130
+ const indexesOffset = {
131
+ r: 0,
132
+ g: 1,
133
+ b: 2,
134
+ a: 3
135
+ },
136
+ alphaFactor = 255;
125
137
  pixels[pos.y][pos.x] = {
126
- r: imageData[i],
127
- g: imageData[i + 1],
128
- b: imageData[i + 2],
129
- a: imageData[i + 3] / 255
138
+ r: imageData[i + indexesOffset.r],
139
+ g: imageData[i + indexesOffset.g],
140
+ b: imageData[i + indexesOffset.b],
141
+ a: imageData[i + indexesOffset.a] / alphaFactor
130
142
  };
131
143
  }
132
144
  return {
@@ -148,7 +160,7 @@ function getImageData(src, offset) {
148
160
  if (!context) {
149
161
  return reject(new Error(`${engine_root_window_.errorPrefix} Could not get canvas context`));
150
162
  }
151
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
163
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
152
164
  resolve(getCanvasImageData(context, canvas, offset));
153
165
  };
154
166
  });
@@ -181,7 +193,7 @@ function getTextData(textOptions, offset, fill) {
181
193
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
182
194
  width: measure.width
183
195
  };
184
- maxWidth = Math.max(maxWidth || 0, lineData.width);
196
+ maxWidth = Math.max(maxWidth || minWidth, lineData.width);
185
197
  totalHeight += lineData.height + linesOptions.spacing;
186
198
  linesData.push(lineData);
187
199
  }
@@ -192,10 +204,10 @@ function getTextData(textOptions, offset, fill) {
192
204
  context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
193
205
  if (fill) {
194
206
  context.fillStyle = color;
195
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
207
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
196
208
  } else {
197
209
  context.strokeStyle = color;
198
- context.strokeText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
210
+ context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
199
211
  }
200
212
  currentHeight += line.height + linesOptions.spacing;
201
213
  }
@@ -205,11 +217,14 @@ function getTextData(textOptions, offset, fill) {
205
217
 
206
218
 
207
219
 
220
+ const maxRetries = 100,
221
+ half = 0.5;
208
222
  class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase {
209
223
  constructor(position, size, fill, options) {
210
224
  super(position, size, fill, options);
211
- const filter = options.filter;
212
- let filterFunc = pixel => pixel.a > 0;
225
+ const filter = options.filter,
226
+ minAlpha = 0;
227
+ let filterFunc = pixel => pixel.a > minAlpha;
213
228
  if (filter !== undefined) {
214
229
  if ((0,engine_root_window_.isString)(filter)) {
215
230
  if (Object.hasOwn(window, filter)) {
@@ -251,8 +266,8 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
251
266
  return;
252
267
  }
253
268
  pixelData = data;
254
- } else if (element || selector) {
255
- const canvas = element || selector && document.querySelector(selector);
269
+ } else if (element ?? selector) {
270
+ const canvas = element ?? (selector && document.querySelector(selector));
256
271
  if (!canvas) {
257
272
  return;
258
273
  }
@@ -274,12 +289,12 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
274
289
  } = this.pixelData,
275
290
  data = this.pixelData,
276
291
  position = this.position,
277
- scale = this.scale;
278
- const positionOffset = {
279
- x: position.x - width * scale / 2,
280
- y: position.y - height * scale / 2
281
- };
282
- for (let i = 0; i < 100; i++) {
292
+ scale = this.scale,
293
+ positionOffset = {
294
+ x: position.x - width * scale * half,
295
+ y: position.y - height * scale * half
296
+ };
297
+ for (let i = 0; i < maxRetries; i++) {
283
298
  const nextIndex = Math.floor((0,engine_root_window_.getRandom)() * width * height),
284
299
  pixelPos = {
285
300
  x: nextIndex % width,
@@ -290,7 +305,7 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
290
305
  if (!shouldCreateParticle) {
291
306
  continue;
292
307
  }
293
- return {
308
+ return Promise.resolve({
294
309
  position: {
295
310
  x: pixelPos.x * scale + positionOffset.x,
296
311
  y: pixelPos.y * scale + positionOffset.y
@@ -299,9 +314,9 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
299
314
  ...pixel
300
315
  },
301
316
  opacity: pixel.a
302
- };
317
+ });
303
318
  }
304
- return null;
319
+ return Promise.resolve(null);
305
320
  }
306
321
  resize(position, size) {
307
322
  super.resize(position, size);
@@ -396,9 +411,10 @@ class TextOptions {
396
411
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/EmittersCanvasShapeOptions.js
397
412
 
398
413
 
414
+ const minAlpha = 0;
399
415
  class EmittersCanvasShapeOptions {
400
416
  constructor() {
401
- this.filter = pixel => pixel.a > 0;
417
+ this.filter = pixel => pixel.a > minAlpha;
402
418
  this.pixels = new PixelsOptions();
403
419
  this.scale = 1;
404
420
  this.selector = "";
@@ -441,7 +457,7 @@ class EmittersCanvasShapeGenerator {
441
457
 
442
458
  async function loadEmittersShapeCanvas(engine, refresh = true) {
443
459
  const emittersEngine = engine;
444
- emittersEngine.addEmitterShapeGenerator && emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator());
460
+ emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
445
461
  await emittersEngine.refresh(refresh);
446
462
  }
447
463
  })();
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see tsparticles.plugin.emitters.shape.canvas.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 s in i)("object"==typeof exports?exports:t)[s]=i[s]}}(this,((t,e)=>(()=>{"use strict";var i={533:t=>{t.exports=e},68:e=>{e.exports=t}},s={};function o(t){var e=s[t];if(void 0!==e)return e.exports;var r=s[t]={exports:{}};return i[t](r,r.exports,o),r.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var r={};return(()=>{o.r(r),o.d(r,{loadEmittersShapeCanvas:()=>f});var t=o(68),e=o(533);function i(t,e,i,s=!0){const o=t.getImageData(0,0,e.width,e.height).data;s&&t.clearRect(0,0,e.width,e.height);const r=[];for(let t=0;t<o.length;t+=i){const s=t/i,n={x:s%e.width,y:Math.floor(s/e.width)};r[n.y]||(r[n.y]=[]),r[n.y][n.x]={r:o[t],g:o[t+1],b:o[t+2],a:o[t+3]/255}}return{pixels:r,width:Math.min(...r.map((t=>t.length))),height:r.length}}class s extends t.EmitterShapeBase{constructor(t,i,s,o){super(t,i,s,o);const r=o.filter;let n=t=>t.a>0;if(void 0!==r)if((0,e.isString)(r)){if(Object.hasOwn(window,r)){const t=window[r];(0,e.isFunction)(t)&&(n=t)}}else n=r;this.filter=n,this.scale=o.scale,this.pixelData={pixels:[],height:0,width:0}}async init(){let t;const s=this.options,o=s.selector,r=s.pixels,n=s.image,a=s.element,l=s.text,c=r.offset;if(n){const s=n.src;if(!s)return;t=await function(t,s){const o=new Image;o.crossOrigin="Anonymous";const r=new Promise(((t,r)=>{o.onerror=r,o.onload=()=>{const n=document.createElement("canvas");n.width=o.width,n.height=o.height;const a=n.getContext("2d");if(!a)return r(new Error(`${e.errorPrefix} Could not get canvas context`));a.drawImage(o,0,0,o.width,o.height,0,0,n.width,n.height),t(i(a,n,s))}}));return o.src=t,r}(s,c)}else if(l){const s=function(t,s,o){const r=document.createElement("canvas"),n=r.getContext("2d"),{font:a,text:l,lines:c,color:h}=t;if(!l||!n)return;const d=l.split(c.separator),f=(0,e.isNumber)(a.size)?`${a.size}px`:a.size,p=[];let u=0,g=0;for(const t of d){n.font=`${a.style||""} ${a.variant||""} ${a.weight||""} ${f} ${a.family}`;const e=n.measureText(t),i={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};u=Math.max(u||0,i.width),g+=i.height+c.spacing,p.push(i)}r.width=u,r.height=g;let x=0;for(const t of p)n.font=`${a.style||""} ${a.variant||""} ${a.weight||""} ${f} ${a.family}`,o?(n.fillStyle=h,n.fillText(t.text,0,x+t.measure.actualBoundingBoxAscent)):(n.strokeStyle=h,n.strokeText(t.text,0,x+t.measure.actualBoundingBoxAscent)),x+=t.height+c.spacing;return i(n,r,s)}(l,c,this.fill);if(!s)return;t=s}else if(a||o){const e=a||o&&document.querySelector(o);if(!e)return;const s=e.getContext("2d");if(!s)return;t=i(s,e,c)}t&&(this.pixelData=t)}async randomPosition(){const{height:t,width:i}=this.pixelData,s=this.pixelData,o=this.position,r=this.scale,n=o.x-i*r/2,a=o.y-t*r/2;for(let o=0;o<100;o++){const o=Math.floor((0,e.getRandom)()*i*t),l={x:o%i,y:Math.floor(o/i)},c=s.pixels[l.y][l.x];if(this.filter(c))return{position:{x:l.x*r+n,y:l.y*r+a},color:{...c},opacity:c.a}}return null}resize(t,e){super.resize(t,e)}}class n{constructor(){this.offset=4}load(t){t&&void 0!==t.offset&&(this.offset=t.offset)}}class a{constructor(){this.family="Verdana",this.size=32,this.style="",this.variant="",this.weight=""}load(t){t&&(void 0!==t.family&&(this.family=t.family),void 0!==t.size&&(this.size=t.size),void 0!==t.style&&(this.style=t.style),void 0!==t.variant&&(this.variant=t.variant),void 0!==t.weight&&(this.weight=t.weight))}}class l{constructor(){this.separator="\n",this.spacing=0}load(t){t&&(void 0!==t.separator&&(this.separator=t.separator),void 0!==t.spacing&&(this.spacing=t.spacing))}}class c{constructor(){this.color="#000000",this.font=new a,this.lines=new l,this.text=""}load(t){t&&(void 0!==t.color&&(this.color=t.color),this.font.load(t.font),this.lines.load(t.lines),void 0!==t.text&&(this.text=t.text))}}class h{constructor(){this.filter=t=>t.a>0,this.pixels=new n,this.scale=1,this.selector="",this.text=new c}load(t){t&&(void 0!==t.element&&(this.element=t.element),void 0!==t.filter&&(this.filter=t.filter),this.pixels.load(t.pixels),void 0!==t.scale&&(this.scale=t.scale),void 0!==t.selector&&(this.selector=t.selector),void 0!==t.image&&(this.image=t.image),this.text.load(t.text))}}class d{generate(t,e,i,o){const r=new h;return r.load(o),new s(t,e,i,r)}}async function f(t,e=!0){const i=t;i.addEmitterShapeGenerator&&i.addEmitterShapeGenerator("canvas",new d),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 i="object"==typeof exports?e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine")):e(t.window,t.window);for(var s in i)("object"==typeof exports?exports:t)[s]=i[s]}}(this,((t,e)=>(()=>{"use strict";var i={533:t=>{t.exports=e},68:e=>{e.exports=t}},s={};function o(t){var e=s[t];if(void 0!==e)return e.exports;var r=s[t]={exports:{}};return i[t](r,r.exports,o),r.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var r={};return(()=>{o.r(r),o.d(r,{loadEmittersShapeCanvas:()=>u});var t=o(68),e=o(533);const i={x:0,y:0};function s(t,e,s,o=!0){const r=t.getImageData(i.x,i.y,e.width,e.height).data;o&&t.clearRect(i.x,i.y,e.width,e.height);const n=[];for(let t=0;t<r.length;t+=s){const i=t/s,o={x:i%e.width,y:Math.floor(i/e.width)};n[o.y]||(n[o.y]=[]);const a={r:0,g:1,b:2,a:3},l=255;n[o.y][o.x]={r:r[t+a.r],g:r[t+a.g],b:r[t+a.b],a:r[t+a.a]/l}}return{pixels:n,width:Math.min(...n.map((t=>t.length))),height:n.length}}class n extends t.EmitterShapeBase{constructor(t,i,s,o){super(t,i,s,o);const r=o.filter;let n=t=>t.a>0;if(void 0!==r)if((0,e.isString)(r)){if(Object.hasOwn(window,r)){const t=window[r];(0,e.isFunction)(t)&&(n=t)}}else n=r;this.filter=n,this.scale=o.scale,this.pixelData={pixels:[],height:0,width:0}}async init(){let t;const o=this.options,r=o.selector,n=o.pixels,a=o.image,l=o.element,c=o.text,h=n.offset;if(a){const o=a.src;if(!o)return;t=await function(t,o){const r=new Image;r.crossOrigin="Anonymous";const n=new Promise(((t,n)=>{r.onerror=n,r.onload=()=>{const a=document.createElement("canvas");a.width=r.width,a.height=r.height;const l=a.getContext("2d");if(!l)return n(new Error(`${e.errorPrefix} Could not get canvas context`));l.drawImage(r,i.x,i.y,r.width,r.height,i.x,i.y,a.width,a.height),t(s(l,a,o))}}));return r.src=t,n}(o,h)}else if(c){const o=function(t,o,r){const n=document.createElement("canvas"),a=n.getContext("2d"),{font:l,text:c,lines:h,color:d}=t;if(!c||!a)return;const f=c.split(h.separator),u=(0,e.isNumber)(l.size)?`${l.size}px`:l.size,p=[];let x=0,g=0;for(const t of f){a.font=`${l.style||""} ${l.variant||""} ${l.weight||""} ${u} ${l.family}`;const e=a.measureText(t),i={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};x=Math.max(x||0,i.width),g+=i.height+h.spacing,p.push(i)}n.width=x,n.height=g;let m=0;for(const t of p)a.font=`${l.style||""} ${l.variant||""} ${l.weight||""} ${u} ${l.family}`,r?(a.fillStyle=d,a.fillText(t.text,i.x,m+t.measure.actualBoundingBoxAscent)):(a.strokeStyle=d,a.strokeText(t.text,i.x,m+t.measure.actualBoundingBoxAscent)),m+=t.height+h.spacing;return s(a,n,o)}(c,h,this.fill);if(!o)return;t=o}else if(l??r){const e=l??(r&&document.querySelector(r));if(!e)return;const i=e.getContext("2d");if(!i)return;t=s(i,e,h)}t&&(this.pixelData=t)}async randomPosition(){const{height:t,width:i}=this.pixelData,s=this.pixelData,o=this.position,r=this.scale,n=o.x-i*r*.5,a=o.y-t*r*.5;for(let o=0;o<100;o++){const o=Math.floor((0,e.getRandom)()*i*t),l={x:o%i,y:Math.floor(o/i)},c=s.pixels[l.y][l.x];if(this.filter(c))return Promise.resolve({position:{x:l.x*r+n,y:l.y*r+a},color:{...c},opacity:c.a})}return Promise.resolve(null)}resize(t,e){super.resize(t,e)}}class a{constructor(){this.offset=4}load(t){t&&void 0!==t.offset&&(this.offset=t.offset)}}class l{constructor(){this.family="Verdana",this.size=32,this.style="",this.variant="",this.weight=""}load(t){t&&(void 0!==t.family&&(this.family=t.family),void 0!==t.size&&(this.size=t.size),void 0!==t.style&&(this.style=t.style),void 0!==t.variant&&(this.variant=t.variant),void 0!==t.weight&&(this.weight=t.weight))}}class c{constructor(){this.separator="\n",this.spacing=0}load(t){t&&(void 0!==t.separator&&(this.separator=t.separator),void 0!==t.spacing&&(this.spacing=t.spacing))}}class h{constructor(){this.color="#000000",this.font=new l,this.lines=new c,this.text=""}load(t){t&&(void 0!==t.color&&(this.color=t.color),this.font.load(t.font),this.lines.load(t.lines),void 0!==t.text&&(this.text=t.text))}}class d{constructor(){this.filter=t=>t.a>0,this.pixels=new a,this.scale=1,this.selector="",this.text=new h}load(t){t&&(void 0!==t.element&&(this.element=t.element),void 0!==t.filter&&(this.filter=t.filter),this.pixels.load(t.pixels),void 0!==t.scale&&(this.scale=t.scale),void 0!==t.selector&&(this.selector=t.selector),void 0!==t.image&&(this.image=t.image),this.text.load(t.text))}}class f{generate(t,e,i,s){const o=new d;return o.load(s),new n(t,e,i,o)}}async function u(t,e=!0){const i=t;i.addEmitterShapeGenerator?.("canvas",new f),await i.refresh(e)}})(),r})()));
@@ -1 +1 @@
1
- /*! tsParticles Emitters Shape Canvas Plugin v3.0.2 by Matteo Bruni */
1
+ /*! tsParticles Emitters Shape Canvas Plugin v3.1.0 by Matteo Bruni */
package/types/types.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import type { IRgba } from "@tsparticles/engine";
2
- export type CanvasPixelData = {
2
+ export interface CanvasPixelData {
3
3
  height: number;
4
4
  pixels: IRgba[][];
5
5
  width: number;
6
- };
7
- export type TextLineData = {
6
+ }
7
+ export interface TextLineData {
8
8
  height: number;
9
9
  measure: TextMetrics;
10
10
  text: string;
11
11
  width: number;
12
- };
12
+ }
package/types/utils.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { CanvasPixelData } from "./types.js";
2
- import type { IDimension } from "@tsparticles/engine";
2
+ import { type IDimension } from "@tsparticles/engine";
3
3
  import type { TextOptions } from "./Options/Classes/TextOptions.js";
4
4
  export declare function getCanvasImageData(ctx: CanvasRenderingContext2D, size: IDimension, offset: number, clear?: boolean): CanvasPixelData;
5
5
  export declare function getImageData(src: string, offset: number): Promise<CanvasPixelData>;
@@ -13,11 +13,12 @@
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 maxRetries = 100, half = 0.5;
16
17
  class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
17
18
  constructor(position, size, fill, options) {
18
19
  super(position, size, fill, options);
19
- const filter = options.filter;
20
- let filterFunc = (pixel) => pixel.a > 0;
20
+ const filter = options.filter, minAlpha = 0;
21
+ let filterFunc = (pixel) => pixel.a > minAlpha;
21
22
  if (filter !== undefined) {
22
23
  if ((0, engine_1.isString)(filter)) {
23
24
  if (Object.hasOwn(window, filter)) {
@@ -56,8 +57,8 @@
56
57
  }
57
58
  pixelData = data;
58
59
  }
59
- else if (element || selector) {
60
- const canvas = element || (selector && document.querySelector(selector));
60
+ else if (element ?? selector) {
61
+ const canvas = element ?? (selector && document.querySelector(selector));
61
62
  if (!canvas) {
62
63
  return;
63
64
  }
@@ -73,12 +74,11 @@
73
74
  this.pixelData = pixelData;
74
75
  }
75
76
  async randomPosition() {
76
- const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale;
77
- const positionOffset = {
78
- x: position.x - (width * scale) / 2,
79
- y: position.y - (height * scale) / 2,
77
+ const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
78
+ x: position.x - width * scale * half,
79
+ y: position.y - height * scale * half,
80
80
  };
81
- for (let i = 0; i < 100; i++) {
81
+ for (let i = 0; i < maxRetries; i++) {
82
82
  const nextIndex = Math.floor((0, engine_1.getRandom)() * width * height), pixelPos = {
83
83
  x: nextIndex % width,
84
84
  y: Math.floor(nextIndex / width),
@@ -86,16 +86,16 @@
86
86
  if (!shouldCreateParticle) {
87
87
  continue;
88
88
  }
89
- return {
89
+ return Promise.resolve({
90
90
  position: {
91
91
  x: pixelPos.x * scale + positionOffset.x,
92
92
  y: pixelPos.y * scale + positionOffset.y,
93
93
  },
94
94
  color: { ...pixel },
95
95
  opacity: pixel.a,
96
- };
96
+ });
97
97
  }
98
- return null;
98
+ return Promise.resolve(null);
99
99
  }
100
100
  resize(position, size) {
101
101
  super.resize(position, size);
@@ -12,9 +12,10 @@
12
12
  exports.EmittersCanvasShapeOptions = void 0;
13
13
  const PixelsOptions_js_1 = require("./PixelsOptions.js");
14
14
  const TextOptions_js_1 = require("./TextOptions.js");
15
+ const minAlpha = 0;
15
16
  class EmittersCanvasShapeOptions {
16
17
  constructor() {
17
- this.filter = (pixel) => pixel.a > 0;
18
+ this.filter = (pixel) => pixel.a > minAlpha;
18
19
  this.pixels = new PixelsOptions_js_1.PixelsOptions();
19
20
  this.scale = 1;
20
21
  this.selector = "";
package/umd/index.js CHANGED
@@ -13,8 +13,7 @@
13
13
  const EmittersCanvasShapeGenerator_js_1 = require("./EmittersCanvasShapeGenerator.js");
14
14
  async function loadEmittersShapeCanvas(engine, refresh = true) {
15
15
  const emittersEngine = engine;
16
- emittersEngine.addEmitterShapeGenerator &&
17
- emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
16
+ emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
18
17
  await emittersEngine.refresh(refresh);
19
18
  }
20
19
  exports.loadEmittersShapeCanvas = loadEmittersShapeCanvas;
package/umd/utils.js CHANGED
@@ -11,10 +11,14 @@
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.getTextData = exports.getImageData = exports.getCanvasImageData = void 0;
13
13
  const engine_1 = require("@tsparticles/engine");
14
+ const origin = {
15
+ x: 0,
16
+ y: 0,
17
+ }, minWidth = 0;
14
18
  function getCanvasImageData(ctx, size, offset, clear = true) {
15
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
19
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
16
20
  if (clear) {
17
- ctx.clearRect(0, 0, size.width, size.height);
21
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
18
22
  }
19
23
  const pixels = [];
20
24
  for (let i = 0; i < imageData.length; i += offset) {
@@ -25,11 +29,17 @@
25
29
  if (!pixels[pos.y]) {
26
30
  pixels[pos.y] = [];
27
31
  }
32
+ const indexesOffset = {
33
+ r: 0,
34
+ g: 1,
35
+ b: 2,
36
+ a: 3,
37
+ }, alphaFactor = 255;
28
38
  pixels[pos.y][pos.x] = {
29
- r: imageData[i],
30
- g: imageData[i + 1],
31
- b: imageData[i + 2],
32
- a: imageData[i + 3] / 255,
39
+ r: imageData[i + indexesOffset.r],
40
+ g: imageData[i + indexesOffset.g],
41
+ b: imageData[i + indexesOffset.b],
42
+ a: imageData[i + indexesOffset.a] / alphaFactor,
33
43
  };
34
44
  }
35
45
  return {
@@ -52,7 +62,7 @@
52
62
  if (!context) {
53
63
  return reject(new Error(`${engine_1.errorPrefix} Could not get canvas context`));
54
64
  }
55
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
65
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
56
66
  resolve(getCanvasImageData(context, canvas, offset));
57
67
  };
58
68
  });
@@ -75,7 +85,7 @@
75
85
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
76
86
  width: measure.width,
77
87
  };
78
- maxWidth = Math.max(maxWidth || 0, lineData.width);
88
+ maxWidth = Math.max(maxWidth || minWidth, lineData.width);
79
89
  totalHeight += lineData.height + linesOptions.spacing;
80
90
  linesData.push(lineData);
81
91
  }
@@ -86,11 +96,11 @@
86
96
  context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
87
97
  if (fill) {
88
98
  context.fillStyle = color;
89
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
99
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
90
100
  }
91
101
  else {
92
102
  context.strokeStyle = color;
93
- context.strokeText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
103
+ context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
94
104
  }
95
105
  currentHeight += line.height + linesOptions.spacing;
96
106
  }