@tsparticles/plugin-canvas-mask 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,8 +1,7 @@
1
- import { addParticlesFromCanvasPixels, getCanvasImageData, getImageData, getTextData } from "./utils.js";
1
+ import { addParticlesFromCanvasPixels, getCanvasImageData, getImageData, getTextData, } from "./utils.js";
2
2
  export class CanvasMaskInstance {
3
- constructor(container, engine) {
3
+ constructor(container) {
4
4
  this._container = container;
5
- this._engine = engine;
6
5
  }
7
6
  async init() {
8
7
  const container = this._container, options = container.actualOptions.canvasMask;
@@ -30,8 +29,8 @@ export class CanvasMaskInstance {
30
29
  }
31
30
  pixelData = data;
32
31
  }
33
- else if (options.element || options.selector) {
34
- const canvas = options.element || (options.selector && document.querySelector(options.selector));
32
+ else if (options.element ?? options.selector) {
33
+ const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
35
34
  if (!canvas) {
36
35
  return;
37
36
  }
@@ -1,7 +1,8 @@
1
1
  import { isFunction, isString } from "@tsparticles/engine";
2
+ const minAlpha = 0;
2
3
  export class CanvasMaskPixels {
3
4
  constructor() {
4
- this.filter = (pixel) => pixel.a > 0;
5
+ this.filter = (pixel) => pixel.a > minAlpha;
5
6
  this.offset = 4;
6
7
  }
7
8
  load(data) {
package/browser/index.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { CanvasMask } from "./Options/Classes/CanvasMask.js";
2
2
  import { CanvasMaskInstance } from "./CanvasMaskInstance.js";
3
3
  class CanvasMaskPlugin {
4
- constructor(engine) {
4
+ constructor() {
5
5
  this.id = "canvasMask";
6
- this._engine = engine;
7
6
  }
8
7
  getPlugin(container) {
9
- return new CanvasMaskInstance(container, this._engine);
8
+ return new CanvasMaskInstance(container);
10
9
  }
11
10
  loadOptions(options, source) {
12
11
  if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
@@ -23,5 +22,5 @@ class CanvasMaskPlugin {
23
22
  }
24
23
  }
25
24
  export async function loadCanvasMaskPlugin(engine, refresh = true) {
26
- await engine.addPlugin(new CanvasMaskPlugin(engine), refresh);
25
+ await engine.addPlugin(new CanvasMaskPlugin(), refresh);
27
26
  }
package/browser/utils.js CHANGED
@@ -1,13 +1,17 @@
1
- import { errorPrefix, getRandom, isNumber, } from "@tsparticles/engine";
1
+ import { errorPrefix, getRandom, isNumber, percentDenominator, } from "@tsparticles/engine";
2
+ const half = 0.5, origin = {
3
+ x: 0,
4
+ y: 0,
5
+ }, defaultWidth = 0;
2
6
  export function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
3
7
  const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
4
8
  let selectedPixels = 0;
5
9
  const positionOffset = {
6
- x: (canvasSize.width * position.x) / 100 - (width * scale) / 2,
7
- y: (canvasSize.height * position.y) / 100 - (height * scale) / 2,
10
+ x: (canvasSize.width * position.x) / percentDenominator - width * scale * half,
11
+ y: (canvasSize.height * position.y) / percentDenominator - height * scale * half,
8
12
  };
9
13
  while (selectedPixels < maxParticles && indexArray.length) {
10
- const nextIndex = indexArray.pop() || 0, pixelPos = {
14
+ const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
11
15
  x: nextIndex % width,
12
16
  y: Math.floor(nextIndex / width),
13
17
  }, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
@@ -33,9 +37,9 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
33
37
  }
34
38
  }
35
39
  export function getCanvasImageData(ctx, size, offset, clear = true) {
36
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
40
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
37
41
  if (clear) {
38
- ctx.clearRect(0, 0, size.width, size.height);
42
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
39
43
  }
40
44
  const pixels = [];
41
45
  for (let i = 0; i < imageData.length; i += offset) {
@@ -46,11 +50,17 @@ export function getCanvasImageData(ctx, size, offset, clear = true) {
46
50
  if (!pixels[pos.y]) {
47
51
  pixels[pos.y] = [];
48
52
  }
53
+ const indexesOffset = {
54
+ r: 0,
55
+ g: 1,
56
+ b: 2,
57
+ a: 3,
58
+ }, alphaFactor = 255;
49
59
  pixels[pos.y][pos.x] = {
50
- r: imageData[i],
51
- g: imageData[i + 1],
52
- b: imageData[i + 2],
53
- a: imageData[i + 3] / 255,
60
+ r: imageData[i + indexesOffset.r],
61
+ g: imageData[i + indexesOffset.g],
62
+ b: imageData[i + indexesOffset.b],
63
+ a: imageData[i + indexesOffset.a] / alphaFactor,
54
64
  };
55
65
  }
56
66
  return {
@@ -72,7 +82,7 @@ export function getImageData(src, offset) {
72
82
  if (!context) {
73
83
  return reject(new Error(`${errorPrefix} Could not get canvas context`));
74
84
  }
75
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
85
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
76
86
  resolve(getCanvasImageData(context, canvas, offset));
77
87
  };
78
88
  });
@@ -87,14 +97,14 @@ export function getTextData(textOptions, offset) {
87
97
  const lines = text.split(linesOptions.separator), fontSize = isNumber(font.size) ? `${font.size}px` : font.size, linesData = [];
88
98
  let maxWidth = 0, totalHeight = 0;
89
99
  for (const line of lines) {
90
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
100
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
91
101
  const measure = context.measureText(line), lineData = {
92
102
  measure,
93
103
  text: line,
94
104
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
95
105
  width: measure.width,
96
106
  };
97
- maxWidth = Math.max(maxWidth || 0, lineData.width);
107
+ maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
98
108
  totalHeight += lineData.height + linesOptions.spacing;
99
109
  linesData.push(lineData);
100
110
  }
@@ -102,15 +112,16 @@ export function getTextData(textOptions, offset) {
102
112
  canvas.height = totalHeight;
103
113
  let currentHeight = 0;
104
114
  for (const line of linesData) {
105
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
115
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
106
116
  context.fillStyle = color;
107
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
117
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
108
118
  currentHeight += line.height + linesOptions.spacing;
109
119
  }
110
120
  return getCanvasImageData(context, canvas, offset);
111
121
  }
112
122
  function shuffle(array) {
113
- for (let currentIndex = array.length - 1; currentIndex >= 0; currentIndex--) {
123
+ const lengthOffset = 1, minIndex = 0;
124
+ for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
114
125
  const randomIndex = Math.floor(getRandom() * currentIndex);
115
126
  [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
116
127
  }
@@ -3,9 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CanvasMaskInstance = void 0;
4
4
  const utils_js_1 = require("./utils.js");
5
5
  class CanvasMaskInstance {
6
- constructor(container, engine) {
6
+ constructor(container) {
7
7
  this._container = container;
8
- this._engine = engine;
9
8
  }
10
9
  async init() {
11
10
  const container = this._container, options = container.actualOptions.canvasMask;
@@ -33,8 +32,8 @@ class CanvasMaskInstance {
33
32
  }
34
33
  pixelData = data;
35
34
  }
36
- else if (options.element || options.selector) {
37
- const canvas = options.element || (options.selector && document.querySelector(options.selector));
35
+ else if (options.element ?? options.selector) {
36
+ const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
38
37
  if (!canvas) {
39
38
  return;
40
39
  }
@@ -2,9 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CanvasMaskPixels = void 0;
4
4
  const engine_1 = require("@tsparticles/engine");
5
+ const minAlpha = 0;
5
6
  class CanvasMaskPixels {
6
7
  constructor() {
7
- this.filter = (pixel) => pixel.a > 0;
8
+ this.filter = (pixel) => pixel.a > minAlpha;
8
9
  this.offset = 4;
9
10
  }
10
11
  load(data) {
package/cjs/index.js CHANGED
@@ -4,12 +4,11 @@ exports.loadCanvasMaskPlugin = void 0;
4
4
  const CanvasMask_js_1 = require("./Options/Classes/CanvasMask.js");
5
5
  const CanvasMaskInstance_js_1 = require("./CanvasMaskInstance.js");
6
6
  class CanvasMaskPlugin {
7
- constructor(engine) {
7
+ constructor() {
8
8
  this.id = "canvasMask";
9
- this._engine = engine;
10
9
  }
11
10
  getPlugin(container) {
12
- return new CanvasMaskInstance_js_1.CanvasMaskInstance(container, this._engine);
11
+ return new CanvasMaskInstance_js_1.CanvasMaskInstance(container);
13
12
  }
14
13
  loadOptions(options, source) {
15
14
  if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
@@ -26,6 +25,6 @@ class CanvasMaskPlugin {
26
25
  }
27
26
  }
28
27
  async function loadCanvasMaskPlugin(engine, refresh = true) {
29
- await engine.addPlugin(new CanvasMaskPlugin(engine), refresh);
28
+ await engine.addPlugin(new CanvasMaskPlugin(), refresh);
30
29
  }
31
30
  exports.loadCanvasMaskPlugin = loadCanvasMaskPlugin;
package/cjs/utils.js CHANGED
@@ -2,15 +2,19 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTextData = exports.getImageData = exports.getCanvasImageData = exports.addParticlesFromCanvasPixels = void 0;
4
4
  const engine_1 = require("@tsparticles/engine");
5
+ const half = 0.5, origin = {
6
+ x: 0,
7
+ y: 0,
8
+ }, defaultWidth = 0;
5
9
  function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
6
10
  const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
7
11
  let selectedPixels = 0;
8
12
  const positionOffset = {
9
- x: (canvasSize.width * position.x) / 100 - (width * scale) / 2,
10
- y: (canvasSize.height * position.y) / 100 - (height * scale) / 2,
13
+ x: (canvasSize.width * position.x) / engine_1.percentDenominator - width * scale * half,
14
+ y: (canvasSize.height * position.y) / engine_1.percentDenominator - height * scale * half,
11
15
  };
12
16
  while (selectedPixels < maxParticles && indexArray.length) {
13
- const nextIndex = indexArray.pop() || 0, pixelPos = {
17
+ const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
14
18
  x: nextIndex % width,
15
19
  y: Math.floor(nextIndex / width),
16
20
  }, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
@@ -37,9 +41,9 @@ function addParticlesFromCanvasPixels(container, data, position, scale, override
37
41
  }
38
42
  exports.addParticlesFromCanvasPixels = addParticlesFromCanvasPixels;
39
43
  function getCanvasImageData(ctx, size, offset, clear = true) {
40
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
44
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
41
45
  if (clear) {
42
- ctx.clearRect(0, 0, size.width, size.height);
46
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
43
47
  }
44
48
  const pixels = [];
45
49
  for (let i = 0; i < imageData.length; i += offset) {
@@ -50,11 +54,17 @@ function getCanvasImageData(ctx, size, offset, clear = true) {
50
54
  if (!pixels[pos.y]) {
51
55
  pixels[pos.y] = [];
52
56
  }
57
+ const indexesOffset = {
58
+ r: 0,
59
+ g: 1,
60
+ b: 2,
61
+ a: 3,
62
+ }, alphaFactor = 255;
53
63
  pixels[pos.y][pos.x] = {
54
- r: imageData[i],
55
- g: imageData[i + 1],
56
- b: imageData[i + 2],
57
- a: imageData[i + 3] / 255,
64
+ r: imageData[i + indexesOffset.r],
65
+ g: imageData[i + indexesOffset.g],
66
+ b: imageData[i + indexesOffset.b],
67
+ a: imageData[i + indexesOffset.a] / alphaFactor,
58
68
  };
59
69
  }
60
70
  return {
@@ -77,7 +87,7 @@ function getImageData(src, offset) {
77
87
  if (!context) {
78
88
  return reject(new Error(`${engine_1.errorPrefix} Could not get canvas context`));
79
89
  }
80
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
90
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
81
91
  resolve(getCanvasImageData(context, canvas, offset));
82
92
  };
83
93
  });
@@ -93,14 +103,14 @@ function getTextData(textOptions, offset) {
93
103
  const lines = text.split(linesOptions.separator), fontSize = (0, engine_1.isNumber)(font.size) ? `${font.size}px` : font.size, linesData = [];
94
104
  let maxWidth = 0, totalHeight = 0;
95
105
  for (const line of lines) {
96
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
106
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
97
107
  const measure = context.measureText(line), lineData = {
98
108
  measure,
99
109
  text: line,
100
110
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
101
111
  width: measure.width,
102
112
  };
103
- maxWidth = Math.max(maxWidth || 0, lineData.width);
113
+ maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
104
114
  totalHeight += lineData.height + linesOptions.spacing;
105
115
  linesData.push(lineData);
106
116
  }
@@ -108,16 +118,17 @@ function getTextData(textOptions, offset) {
108
118
  canvas.height = totalHeight;
109
119
  let currentHeight = 0;
110
120
  for (const line of linesData) {
111
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
121
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
112
122
  context.fillStyle = color;
113
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
123
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
114
124
  currentHeight += line.height + linesOptions.spacing;
115
125
  }
116
126
  return getCanvasImageData(context, canvas, offset);
117
127
  }
118
128
  exports.getTextData = getTextData;
119
129
  function shuffle(array) {
120
- for (let currentIndex = array.length - 1; currentIndex >= 0; currentIndex--) {
130
+ const lengthOffset = 1, minIndex = 0;
131
+ for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
121
132
  const randomIndex = Math.floor((0, engine_1.getRandom)() * currentIndex);
122
133
  [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
123
134
  }
@@ -1,8 +1,7 @@
1
- import { addParticlesFromCanvasPixels, getCanvasImageData, getImageData, getTextData } from "./utils.js";
1
+ import { addParticlesFromCanvasPixels, getCanvasImageData, getImageData, getTextData, } from "./utils.js";
2
2
  export class CanvasMaskInstance {
3
- constructor(container, engine) {
3
+ constructor(container) {
4
4
  this._container = container;
5
- this._engine = engine;
6
5
  }
7
6
  async init() {
8
7
  const container = this._container, options = container.actualOptions.canvasMask;
@@ -30,8 +29,8 @@ export class CanvasMaskInstance {
30
29
  }
31
30
  pixelData = data;
32
31
  }
33
- else if (options.element || options.selector) {
34
- const canvas = options.element || (options.selector && document.querySelector(options.selector));
32
+ else if (options.element ?? options.selector) {
33
+ const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
35
34
  if (!canvas) {
36
35
  return;
37
36
  }
@@ -1,7 +1,8 @@
1
1
  import { isFunction, isString } from "@tsparticles/engine";
2
+ const minAlpha = 0;
2
3
  export class CanvasMaskPixels {
3
4
  constructor() {
4
- this.filter = (pixel) => pixel.a > 0;
5
+ this.filter = (pixel) => pixel.a > minAlpha;
5
6
  this.offset = 4;
6
7
  }
7
8
  load(data) {
package/esm/index.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { CanvasMask } from "./Options/Classes/CanvasMask.js";
2
2
  import { CanvasMaskInstance } from "./CanvasMaskInstance.js";
3
3
  class CanvasMaskPlugin {
4
- constructor(engine) {
4
+ constructor() {
5
5
  this.id = "canvasMask";
6
- this._engine = engine;
7
6
  }
8
7
  getPlugin(container) {
9
- return new CanvasMaskInstance(container, this._engine);
8
+ return new CanvasMaskInstance(container);
10
9
  }
11
10
  loadOptions(options, source) {
12
11
  if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
@@ -23,5 +22,5 @@ class CanvasMaskPlugin {
23
22
  }
24
23
  }
25
24
  export async function loadCanvasMaskPlugin(engine, refresh = true) {
26
- await engine.addPlugin(new CanvasMaskPlugin(engine), refresh);
25
+ await engine.addPlugin(new CanvasMaskPlugin(), refresh);
27
26
  }
package/esm/utils.js CHANGED
@@ -1,13 +1,17 @@
1
- import { errorPrefix, getRandom, isNumber, } from "@tsparticles/engine";
1
+ import { errorPrefix, getRandom, isNumber, percentDenominator, } from "@tsparticles/engine";
2
+ const half = 0.5, origin = {
3
+ x: 0,
4
+ y: 0,
5
+ }, defaultWidth = 0;
2
6
  export function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
3
7
  const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
4
8
  let selectedPixels = 0;
5
9
  const positionOffset = {
6
- x: (canvasSize.width * position.x) / 100 - (width * scale) / 2,
7
- y: (canvasSize.height * position.y) / 100 - (height * scale) / 2,
10
+ x: (canvasSize.width * position.x) / percentDenominator - width * scale * half,
11
+ y: (canvasSize.height * position.y) / percentDenominator - height * scale * half,
8
12
  };
9
13
  while (selectedPixels < maxParticles && indexArray.length) {
10
- const nextIndex = indexArray.pop() || 0, pixelPos = {
14
+ const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
11
15
  x: nextIndex % width,
12
16
  y: Math.floor(nextIndex / width),
13
17
  }, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
@@ -33,9 +37,9 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
33
37
  }
34
38
  }
35
39
  export function getCanvasImageData(ctx, size, offset, clear = true) {
36
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
40
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
37
41
  if (clear) {
38
- ctx.clearRect(0, 0, size.width, size.height);
42
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
39
43
  }
40
44
  const pixels = [];
41
45
  for (let i = 0; i < imageData.length; i += offset) {
@@ -46,11 +50,17 @@ export function getCanvasImageData(ctx, size, offset, clear = true) {
46
50
  if (!pixels[pos.y]) {
47
51
  pixels[pos.y] = [];
48
52
  }
53
+ const indexesOffset = {
54
+ r: 0,
55
+ g: 1,
56
+ b: 2,
57
+ a: 3,
58
+ }, alphaFactor = 255;
49
59
  pixels[pos.y][pos.x] = {
50
- r: imageData[i],
51
- g: imageData[i + 1],
52
- b: imageData[i + 2],
53
- a: imageData[i + 3] / 255,
60
+ r: imageData[i + indexesOffset.r],
61
+ g: imageData[i + indexesOffset.g],
62
+ b: imageData[i + indexesOffset.b],
63
+ a: imageData[i + indexesOffset.a] / alphaFactor,
54
64
  };
55
65
  }
56
66
  return {
@@ -72,7 +82,7 @@ export function getImageData(src, offset) {
72
82
  if (!context) {
73
83
  return reject(new Error(`${errorPrefix} Could not get canvas context`));
74
84
  }
75
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
85
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
76
86
  resolve(getCanvasImageData(context, canvas, offset));
77
87
  };
78
88
  });
@@ -87,14 +97,14 @@ export function getTextData(textOptions, offset) {
87
97
  const lines = text.split(linesOptions.separator), fontSize = isNumber(font.size) ? `${font.size}px` : font.size, linesData = [];
88
98
  let maxWidth = 0, totalHeight = 0;
89
99
  for (const line of lines) {
90
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
100
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
91
101
  const measure = context.measureText(line), lineData = {
92
102
  measure,
93
103
  text: line,
94
104
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
95
105
  width: measure.width,
96
106
  };
97
- maxWidth = Math.max(maxWidth || 0, lineData.width);
107
+ maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
98
108
  totalHeight += lineData.height + linesOptions.spacing;
99
109
  linesData.push(lineData);
100
110
  }
@@ -102,15 +112,16 @@ export function getTextData(textOptions, offset) {
102
112
  canvas.height = totalHeight;
103
113
  let currentHeight = 0;
104
114
  for (const line of linesData) {
105
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
115
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
106
116
  context.fillStyle = color;
107
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
117
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
108
118
  currentHeight += line.height + linesOptions.spacing;
109
119
  }
110
120
  return getCanvasImageData(context, canvas, offset);
111
121
  }
112
122
  function shuffle(array) {
113
- for (let currentIndex = array.length - 1; currentIndex >= 0; currentIndex--) {
123
+ const lengthOffset = 1, minIndex = 0;
124
+ for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
114
125
  const randomIndex = Math.floor(getRandom() * currentIndex);
115
126
  [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
116
127
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/plugin-canvas-mask",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "tsParticles canvas mask plugin",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -86,7 +86,7 @@
86
86
  "./package.json": "./package.json"
87
87
  },
88
88
  "dependencies": {
89
- "@tsparticles/engine": "^3.0.2"
89
+ "@tsparticles/engine": "^3.1.0"
90
90
  },
91
91
  "publishConfig": {
92
92
  "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-canvas-mask [6 Dec 2023 at 17:41]</title>
6
+ <title>@tsparticles/plugin-canvas-mask [13 Jan 2024 at 23:02]</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.canvas-mask.js","isAsset":true,"statSize":10709,"parsedSize":14543,"gzipSize":3869,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":10667,"groups":[{"id":46,"label":"index.js + 9 modules (concatenated)","path":"./dist/browser/index.js + 9 modules (concatenated)","statSize":10667,"parsedSize":14543,"gzipSize":3869,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser","statSize":10667,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/index.js","statSize":876,"parsedSize":1194,"gzipSize":317,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskInstance.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/CanvasMaskInstance.js","statSize":1360,"parsedSize":1854,"gzipSize":493,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes","statSize":3868,"groups":[{"id":null,"label":"CanvasMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMask.js","statSize":1346,"parsedSize":1835,"gzipSize":488,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskOverride.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMaskOverride.js","statSize":314,"parsedSize":428,"gzipSize":113,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskPixels.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMaskPixels.js","statSize":632,"parsedSize":861,"gzipSize":229,"inaccurateSizes":true},{"id":null,"label":"ImageMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/ImageMask.js","statSize":190,"parsedSize":259,"gzipSize":68,"inaccurateSizes":true},{"id":null,"label":"TextMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/TextMask.js","statSize":531,"parsedSize":723,"gzipSize":192,"inaccurateSizes":true},{"id":null,"label":"FontTextMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/FontTextMask.js","statSize":534,"parsedSize":728,"gzipSize":193,"inaccurateSizes":true},{"id":null,"label":"TextMaskLine.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/TextMaskLine.js","statSize":321,"parsedSize":437,"gzipSize":116,"inaccurateSizes":true}],"parsedSize":5273,"gzipSize":1402,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/utils.js","statSize":4563,"parsedSize":6221,"gzipSize":1655,"inaccurateSizes":true}],"parsedSize":14543,"gzipSize":3869,"inaccurateSizes":true}]}],"parsedSize":14543,"gzipSize":3869},{"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}],"isInitialByEntrypoint":{"tsparticles.plugin.canvas-mask":true}}];
34
+ window.chartData = [{"label":"tsparticles.plugin.canvas-mask.js","isAsset":true,"statSize":11137,"parsedSize":14991,"gzipSize":3996,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":11095,"groups":[{"id":763,"label":"index.js + 9 modules (concatenated)","path":"./dist/browser/index.js + 9 modules (concatenated)","statSize":11095,"parsedSize":14991,"gzipSize":3996,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser","statSize":11095,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/index.js","statSize":823,"parsedSize":1111,"gzipSize":296,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskInstance.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/CanvasMaskInstance.js","statSize":1327,"parsedSize":1792,"gzipSize":477,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes","statSize":3895,"groups":[{"id":null,"label":"CanvasMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMask.js","statSize":1346,"parsedSize":1818,"gzipSize":484,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskOverride.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMaskOverride.js","statSize":314,"parsedSize":424,"gzipSize":113,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskPixels.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMaskPixels.js","statSize":659,"parsedSize":890,"gzipSize":237,"inaccurateSizes":true},{"id":null,"label":"ImageMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/ImageMask.js","statSize":190,"parsedSize":256,"gzipSize":68,"inaccurateSizes":true},{"id":null,"label":"TextMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/TextMask.js","statSize":531,"parsedSize":717,"gzipSize":191,"inaccurateSizes":true},{"id":null,"label":"FontTextMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/FontTextMask.js","statSize":534,"parsedSize":721,"gzipSize":192,"inaccurateSizes":true},{"id":null,"label":"TextMaskLine.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/TextMaskLine.js","statSize":321,"parsedSize":433,"gzipSize":115,"inaccurateSizes":true}],"parsedSize":5262,"gzipSize":1402,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/utils.js","statSize":5050,"parsedSize":6823,"gzipSize":1818,"inaccurateSizes":true}],"parsedSize":14991,"gzipSize":3996,"inaccurateSizes":true}]}],"parsedSize":14991,"gzipSize":3996},{"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}],"isInitialByEntrypoint":{"tsparticles.plugin.canvas-mask":true}}];
35
35
  window.entrypoints = ["tsparticles.plugin.canvas-mask","tsparticles.plugin.canvas-mask.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')
@@ -116,9 +116,10 @@ class CanvasMaskOverride {
116
116
  var engine_root_window_ = __webpack_require__(533);
117
117
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/CanvasMaskPixels.js
118
118
 
119
+ const minAlpha = 0;
119
120
  class CanvasMaskPixels {
120
121
  constructor() {
121
- this.filter = pixel => pixel.a > 0;
122
+ this.filter = pixel => pixel.a > minAlpha;
122
123
  this.offset = 4;
123
124
  }
124
125
  load(data) {
@@ -281,6 +282,12 @@ class CanvasMask {
281
282
  }
282
283
  ;// CONCATENATED MODULE: ./dist/browser/utils.js
283
284
 
285
+ const half = 0.5,
286
+ origin = {
287
+ x: 0,
288
+ y: 0
289
+ },
290
+ defaultWidth = 0;
284
291
  function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
285
292
  const {
286
293
  height,
@@ -292,11 +299,12 @@ function addParticlesFromCanvasPixels(container, data, position, scale, override
292
299
  canvasSize = container.canvas.size;
293
300
  let selectedPixels = 0;
294
301
  const positionOffset = {
295
- x: canvasSize.width * position.x / 100 - width * scale / 2,
296
- y: canvasSize.height * position.y / 100 - height * scale / 2
302
+ x: canvasSize.width * position.x / engine_root_window_.percentDenominator - width * scale * half,
303
+ y: canvasSize.height * position.y / engine_root_window_.percentDenominator - height * scale * half
297
304
  };
298
305
  while (selectedPixels < maxParticles && indexArray.length) {
299
- const nextIndex = indexArray.pop() || 0,
306
+ const defaultIndex = 0,
307
+ nextIndex = indexArray.pop() ?? defaultIndex,
300
308
  pixelPos = {
301
309
  x: nextIndex % width,
302
310
  y: Math.floor(nextIndex / width)
@@ -326,9 +334,9 @@ function addParticlesFromCanvasPixels(container, data, position, scale, override
326
334
  }
327
335
  }
328
336
  function getCanvasImageData(ctx, size, offset, clear = true) {
329
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
337
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
330
338
  if (clear) {
331
- ctx.clearRect(0, 0, size.width, size.height);
339
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
332
340
  }
333
341
  const pixels = [];
334
342
  for (let i = 0; i < imageData.length; i += offset) {
@@ -340,11 +348,18 @@ function getCanvasImageData(ctx, size, offset, clear = true) {
340
348
  if (!pixels[pos.y]) {
341
349
  pixels[pos.y] = [];
342
350
  }
351
+ const indexesOffset = {
352
+ r: 0,
353
+ g: 1,
354
+ b: 2,
355
+ a: 3
356
+ },
357
+ alphaFactor = 255;
343
358
  pixels[pos.y][pos.x] = {
344
- r: imageData[i],
345
- g: imageData[i + 1],
346
- b: imageData[i + 2],
347
- a: imageData[i + 3] / 255
359
+ r: imageData[i + indexesOffset.r],
360
+ g: imageData[i + indexesOffset.g],
361
+ b: imageData[i + indexesOffset.b],
362
+ a: imageData[i + indexesOffset.a] / alphaFactor
348
363
  };
349
364
  }
350
365
  return {
@@ -366,7 +381,7 @@ function getImageData(src, offset) {
366
381
  if (!context) {
367
382
  return reject(new Error(`${engine_root_window_.errorPrefix} Could not get canvas context`));
368
383
  }
369
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
384
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
370
385
  resolve(getCanvasImageData(context, canvas, offset));
371
386
  };
372
387
  });
@@ -391,7 +406,7 @@ function getTextData(textOptions, offset) {
391
406
  let maxWidth = 0,
392
407
  totalHeight = 0;
393
408
  for (const line of lines) {
394
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
409
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
395
410
  const measure = context.measureText(line),
396
411
  lineData = {
397
412
  measure,
@@ -399,7 +414,7 @@ function getTextData(textOptions, offset) {
399
414
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
400
415
  width: measure.width
401
416
  };
402
- maxWidth = Math.max(maxWidth || 0, lineData.width);
417
+ maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
403
418
  totalHeight += lineData.height + linesOptions.spacing;
404
419
  linesData.push(lineData);
405
420
  }
@@ -407,15 +422,17 @@ function getTextData(textOptions, offset) {
407
422
  canvas.height = totalHeight;
408
423
  let currentHeight = 0;
409
424
  for (const line of linesData) {
410
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
425
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
411
426
  context.fillStyle = color;
412
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
427
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
413
428
  currentHeight += line.height + linesOptions.spacing;
414
429
  }
415
430
  return getCanvasImageData(context, canvas, offset);
416
431
  }
417
432
  function shuffle(array) {
418
- for (let currentIndex = array.length - 1; currentIndex >= 0; currentIndex--) {
433
+ const lengthOffset = 1,
434
+ minIndex = 0;
435
+ for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
419
436
  const randomIndex = Math.floor((0,engine_root_window_.getRandom)() * currentIndex);
420
437
  [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
421
438
  }
@@ -425,9 +442,8 @@ const range = n => [...Array(n).keys()];
425
442
  ;// CONCATENATED MODULE: ./dist/browser/CanvasMaskInstance.js
426
443
 
427
444
  class CanvasMaskInstance {
428
- constructor(container, engine) {
445
+ constructor(container) {
429
446
  this._container = container;
430
- this._engine = engine;
431
447
  }
432
448
  async init() {
433
449
  const container = this._container,
@@ -454,8 +470,8 @@ class CanvasMaskInstance {
454
470
  return;
455
471
  }
456
472
  pixelData = data;
457
- } else if (options.element || options.selector) {
458
- const canvas = options.element || options.selector && document.querySelector(options.selector);
473
+ } else if (options.element ?? options.selector) {
474
+ const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
459
475
  if (!canvas) {
460
476
  return;
461
477
  }
@@ -472,12 +488,11 @@ class CanvasMaskInstance {
472
488
 
473
489
 
474
490
  class CanvasMaskPlugin {
475
- constructor(engine) {
491
+ constructor() {
476
492
  this.id = "canvasMask";
477
- this._engine = engine;
478
493
  }
479
494
  getPlugin(container) {
480
- return new CanvasMaskInstance(container, this._engine);
495
+ return new CanvasMaskInstance(container);
481
496
  }
482
497
  loadOptions(options, source) {
483
498
  if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
@@ -494,7 +509,7 @@ class CanvasMaskPlugin {
494
509
  }
495
510
  }
496
511
  async function loadCanvasMaskPlugin(engine, refresh = true) {
497
- await engine.addPlugin(new CanvasMaskPlugin(engine), refresh);
512
+ await engine.addPlugin(new CanvasMaskPlugin(), refresh);
498
513
  }
499
514
  })();
500
515
 
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see tsparticles.plugin.canvas-mask.min.js.LICENSE.txt */
2
- !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/engine")):e(t.window);for(var s in i)("object"==typeof exports?exports:t)[s]=i[s]}}(this,(t=>(()=>{"use strict";var e={533:e=>{e.exports=t}},i={};function s(t){var o=i[t];if(void 0!==o)return o.exports;var n=i[t]={exports:{}};return e[t](n,n.exports,s),n.exports}s.d=(t,e)=>{for(var i in e)s.o(e,i)&&!s.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),s.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var o={};return(()=>{s.r(o),s.d(o,{loadCanvasMaskPlugin:()=>p});class t{constructor(){this.color=!0,this.opacity=!1}load(t){t&&(void 0!==t.color&&(this.color=t.color),void 0!==t.opacity&&(this.opacity=t.opacity))}}var e=s(533);class i{constructor(){this.filter=t=>t.a>0,this.offset=4}load(t){if(t){if(void 0!==t.filter)if((0,e.isString)(t.filter)){if(Object.hasOwn(window,t.filter)){const i=window[t.filter];(0,e.isFunction)(i)&&(this.filter=i)}}else this.filter=t.filter;void 0!==t.offset&&(this.offset=t.offset)}}}class n{constructor(){this.src=""}load(t){t&&void 0!==t.src&&(this.src=t.src)}}class r{constructor(){this.family="sans-serif",this.size=100}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 a{constructor(){this.separator="\n",this.spacing=10}load(t){t&&(void 0!==t.separator&&(this.separator=t.separator),void 0!==t.spacing&&(this.spacing=t.spacing))}}class l{constructor(){this.color="#000000",this.font=new r,this.lines=new a,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 c{constructor(){this.enable=!1,this.override=new t,this.pixels=new i,this.position={x:50,y:50},this.scale=1}load(t){t&&(void 0!==t.element&&t.element instanceof HTMLCanvasElement&&(this.element=t.element),void 0!==t.enable&&(this.enable=t.enable),t.image&&(this.image||(this.image=new n),this.image.load(t.image)),this.pixels.load(t.pixels),t.position&&(this.position={x:t.position.x??this.position.x,y:t.position.y??this.position.y}),this.override.load(t.override),void 0!==t.scale&&(this.scale=t.scale),void 0!==t.selector&&(this.selector=t.selector),t.text&&(this.text||(this.text=new l),this.text.load(t.text)))}}function h(t,i,s,o,n,r){const{height:a,width:l}=i,c=a*l,h=function(t){for(let i=t.length-1;i>=0;i--){const s=Math.floor((0,e.getRandom)()*i);[t[i],t[s]]=[t[s],t[i]]}return t}(f(c)),d=Math.min(c,t.actualOptions.particles.number.value),u=t.canvas.size;let g=0;const p=u.width*s.x/100-l*o/2,x=u.height*s.y/100-a*o/2;for(;g<d&&h.length;){const e=h.pop()||0,s={x:e%l,y:Math.floor(e/l)},a=i.pixels[s.y][s.x];if(!r(a))continue;const c={x:s.x*o+p,y:s.y*o+x},d={};n.color&&(d.color={value:a}),n.opacity&&(d.opacity={value:a.a}),t.particles.addParticle(c,d),g++}}function d(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 n=[];for(let t=0;t<o.length;t+=i){const s=t/i,r={x:s%e.width,y:Math.floor(s/e.width)};n[r.y]||(n[r.y]=[]),n[r.y][r.x]={r:o[t],g:o[t+1],b:o[t+2],a:o[t+3]/255}}return{pixels:n,width:Math.min(...n.map((t=>t.length))),height:n.length}}const f=t=>[...Array(t).keys()];class u{constructor(t,e){this._container=t,this._engine=e}async init(){const t=this._container,i=t.actualOptions.canvasMask;if(!i?.enable)return;let s={pixels:[],height:0,width:0};const o=i.pixels.offset;if(i.image){const t=i.image.src;if(!t)return;s=await function(t,i){const s=new Image;s.crossOrigin="Anonymous";const o=new Promise(((t,o)=>{s.onerror=o,s.onload=()=>{const n=document.createElement("canvas");n.width=s.width,n.height=s.height;const r=n.getContext("2d");if(!r)return o(new Error(`${e.errorPrefix} Could not get canvas context`));r.drawImage(s,0,0,s.width,s.height,0,0,n.width,n.height),t(d(r,n,i))}}));return s.src=t,o}(t,o)}else if(i.text){const t=function(t,i){const s=document.createElement("canvas"),o=s.getContext("2d"),{font:n,text:r,lines:a,color:l}=t;if(!r||!o)return;const c=r.split(a.separator),h=(0,e.isNumber)(n.size)?`${n.size}px`:n.size,f=[];let u=0,g=0;for(const t of c){o.font=`${n.style||""} ${n.variant||""} ${n.weight||""} ${h} ${n.family}`;const e=o.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+a.spacing,f.push(i)}s.width=u,s.height=g;let p=0;for(const t of f)o.font=`${n.style||""} ${n.variant||""} ${n.weight||""} ${h} ${n.family}`,o.fillStyle=l,o.fillText(t.text,0,p+t.measure.actualBoundingBoxAscent),p+=t.height+a.spacing;return d(o,s,i)}(i.text,o);if(!t)return;s=t}else if(i.element||i.selector){const t=i.element||i.selector&&document.querySelector(i.selector);if(!t)return;const e=t.getContext("2d");if(!e)return;s=d(e,t,o)}h(t,s,i.position,i.scale,i.override,i.pixels.filter)}}class g{constructor(t){this.id="canvasMask",this._engine=t}getPlugin(t){return new u(t,this._engine)}loadOptions(t,e){if(!this.needsPlugin(t)&&!this.needsPlugin(e))return;let i=t.canvasMask;void 0===i?.load&&(t.canvasMask=i=new c),i.load(e?.canvasMask)}needsPlugin(t){return t?.canvasMask?.enable??!1}}async function p(t,e=!0){await t.addPlugin(new g(t),e)}})(),o})()));
2
+ !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/engine")):e(t.window);for(var o in i)("object"==typeof exports?exports:t)[o]=i[o]}}(this,(t=>(()=>{"use strict";var e={533:e=>{e.exports=t}},i={};function o(t){var s=i[t];if(void 0!==s)return s.exports;var n=i[t]={exports:{}};return e[t](n,n.exports,o),n.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 s={};return(()=>{o.r(s),o.d(s,{loadCanvasMaskPlugin:()=>x});class t{constructor(){this.color=!0,this.opacity=!1}load(t){t&&(void 0!==t.color&&(this.color=t.color),void 0!==t.opacity&&(this.opacity=t.opacity))}}var e=o(533);class i{constructor(){this.filter=t=>t.a>0,this.offset=4}load(t){if(t){if(void 0!==t.filter)if((0,e.isString)(t.filter)){if(Object.hasOwn(window,t.filter)){const i=window[t.filter];(0,e.isFunction)(i)&&(this.filter=i)}}else this.filter=t.filter;void 0!==t.offset&&(this.offset=t.offset)}}}class n{constructor(){this.src=""}load(t){t&&void 0!==t.src&&(this.src=t.src)}}class r{constructor(){this.family="sans-serif",this.size=100}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 a{constructor(){this.separator="\n",this.spacing=10}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 r,this.lines=new a,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 l{constructor(){this.enable=!1,this.override=new t,this.pixels=new i,this.position={x:50,y:50},this.scale=1}load(t){t&&(void 0!==t.element&&t.element instanceof HTMLCanvasElement&&(this.element=t.element),void 0!==t.enable&&(this.enable=t.enable),t.image&&(this.image||(this.image=new n),this.image.load(t.image)),this.pixels.load(t.pixels),t.position&&(this.position={x:t.position.x??this.position.x,y:t.position.y??this.position.y}),this.override.load(t.override),void 0!==t.scale&&(this.scale=t.scale),void 0!==t.selector&&(this.selector=t.selector),t.text&&(this.text||(this.text=new c),this.text.load(t.text)))}}const h={x:0,y:0};function d(t,i,o,s,n,r){const{height:a,width:c}=i,l=a*c,h=function(t){const i=1,o=0;for(let s=t.length-i;s>=o;s--){const i=Math.floor((0,e.getRandom)()*s);[t[s],t[i]]=[t[i],t[s]]}return t}(u(l)),d=Math.min(l,t.actualOptions.particles.number.value),f=t.canvas.size;let p=0;const g=f.width*o.x/e.percentDenominator-c*s*.5,x=f.height*o.y/e.percentDenominator-a*s*.5;for(;p<d&&h.length;){const e=0,o=h.pop()??e,a={x:o%c,y:Math.floor(o/c)},l=i.pixels[a.y][a.x];if(!r(l))continue;const d={x:a.x*s+g,y:a.y*s+x},f={};n.color&&(f.color={value:l}),n.opacity&&(f.opacity={value:l.a}),t.particles.addParticle(d,f),p++}}function f(t,e,i,o=!0){const s=t.getImageData(h.x,h.y,e.width,e.height).data;o&&t.clearRect(h.x,h.y,e.width,e.height);const n=[];for(let t=0;t<s.length;t+=i){const o=t/i,r={x:o%e.width,y:Math.floor(o/e.width)};n[r.y]||(n[r.y]=[]);const a={r:0,g:1,b:2,a:3},c=255;n[r.y][r.x]={r:s[t+a.r],g:s[t+a.g],b:s[t+a.b],a:s[t+a.a]/c}}return{pixels:n,width:Math.min(...n.map((t=>t.length))),height:n.length}}const u=t=>[...Array(t).keys()];class p{constructor(t){this._container=t}async init(){const t=this._container,i=t.actualOptions.canvasMask;if(!i?.enable)return;let o={pixels:[],height:0,width:0};const s=i.pixels.offset;if(i.image){const t=i.image.src;if(!t)return;o=await function(t,i){const o=new Image;o.crossOrigin="Anonymous";const s=new Promise(((t,s)=>{o.onerror=s,o.onload=()=>{const n=document.createElement("canvas");n.width=o.width,n.height=o.height;const r=n.getContext("2d");if(!r)return s(new Error(`${e.errorPrefix} Could not get canvas context`));r.drawImage(o,h.x,h.y,o.width,o.height,h.x,h.y,n.width,n.height),t(f(r,n,i))}}));return o.src=t,s}(t,s)}else if(i.text){const t=function(t,i){const o=document.createElement("canvas"),s=o.getContext("2d"),{font:n,text:r,lines:a,color:c}=t;if(!r||!s)return;const l=r.split(a.separator),d=(0,e.isNumber)(n.size)?`${n.size}px`:n.size,u=[];let p=0,g=0;for(const t of l){s.font=`${n.style??""} ${n.variant??""} ${n.weight??""} ${d} ${n.family}`;const e=s.measureText(t),i={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};p=Math.max(p||0,i.width),g+=i.height+a.spacing,u.push(i)}o.width=p,o.height=g;let x=0;for(const t of u)s.font=`${n.style??""} ${n.variant??""} ${n.weight??""} ${d} ${n.family}`,s.fillStyle=c,s.fillText(t.text,h.x,x+t.measure.actualBoundingBoxAscent),x+=t.height+a.spacing;return f(s,o,i)}(i.text,s);if(!t)return;o=t}else if(i.element??i.selector){const t=i.element??(i.selector&&document.querySelector(i.selector));if(!t)return;const e=t.getContext("2d");if(!e)return;o=f(e,t,s)}d(t,o,i.position,i.scale,i.override,i.pixels.filter)}}class g{constructor(){this.id="canvasMask"}getPlugin(t){return new p(t)}loadOptions(t,e){if(!this.needsPlugin(t)&&!this.needsPlugin(e))return;let i=t.canvasMask;void 0===i?.load&&(t.canvasMask=i=new l),i.load(e?.canvasMask)}needsPlugin(t){return t?.canvasMask?.enable??!1}}async function x(t,e=!0){await t.addPlugin(new g,e)}})(),s})()));
@@ -1 +1 @@
1
- /*! tsParticles Canvas Mask Plugin v3.0.2 by Matteo Bruni */
1
+ /*! tsParticles Canvas Mask Plugin v3.1.0 by Matteo Bruni */
@@ -1,8 +1,7 @@
1
- import type { Engine, IContainerPlugin } from "@tsparticles/engine";
2
1
  import type { CanvasMaskContainer } from "./types.js";
2
+ import type { IContainerPlugin } from "@tsparticles/engine";
3
3
  export declare class CanvasMaskInstance implements IContainerPlugin {
4
4
  private readonly _container;
5
- private readonly _engine;
6
- constructor(container: CanvasMaskContainer, engine: Engine);
5
+ constructor(container: CanvasMaskContainer);
7
6
  init(): Promise<void>;
8
7
  }
@@ -1,4 +1,4 @@
1
- import type { IOptionLoader, IRgba, RecursivePartial } from "@tsparticles/engine";
1
+ import { type IOptionLoader, type IRgba, type RecursivePartial } from "@tsparticles/engine";
2
2
  import type { ICanvasMaskPixels } from "../Interfaces/ICanvasMaskPixels.js";
3
3
  export declare class CanvasMaskPixels implements ICanvasMaskPixels, IOptionLoader<ICanvasMaskPixels> {
4
4
  filter: (pixel: IRgba) => boolean;
package/types/utils.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { type Container, type ICoordinates, type IDimension, type IRgba } from "@tsparticles/engine";
2
2
  import type { ICanvasMaskOverride } from "./Options/Interfaces/ICanvasMaskOverride.js";
3
3
  import type { TextMask } from "./Options/Classes/TextMask.js";
4
- export type CanvasPixelData = {
4
+ export interface CanvasPixelData {
5
5
  height: number;
6
6
  pixels: IRgba[][];
7
7
  width: number;
8
- };
8
+ }
9
9
  export declare function addParticlesFromCanvasPixels(container: Container, data: CanvasPixelData, position: ICoordinates, scale: number, override: ICanvasMaskOverride, filter: (pixel: IRgba) => boolean): void;
10
10
  export declare function getCanvasImageData(ctx: CanvasRenderingContext2D, size: IDimension, offset: number, clear?: boolean): CanvasPixelData;
11
11
  export declare function getImageData(src: string, offset: number): Promise<CanvasPixelData>;
@@ -12,9 +12,8 @@
12
12
  exports.CanvasMaskInstance = void 0;
13
13
  const utils_js_1 = require("./utils.js");
14
14
  class CanvasMaskInstance {
15
- constructor(container, engine) {
15
+ constructor(container) {
16
16
  this._container = container;
17
- this._engine = engine;
18
17
  }
19
18
  async init() {
20
19
  const container = this._container, options = container.actualOptions.canvasMask;
@@ -42,8 +41,8 @@
42
41
  }
43
42
  pixelData = data;
44
43
  }
45
- else if (options.element || options.selector) {
46
- const canvas = options.element || (options.selector && document.querySelector(options.selector));
44
+ else if (options.element ?? options.selector) {
45
+ const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
47
46
  if (!canvas) {
48
47
  return;
49
48
  }
@@ -11,9 +11,10 @@
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.CanvasMaskPixels = void 0;
13
13
  const engine_1 = require("@tsparticles/engine");
14
+ const minAlpha = 0;
14
15
  class CanvasMaskPixels {
15
16
  constructor() {
16
- this.filter = (pixel) => pixel.a > 0;
17
+ this.filter = (pixel) => pixel.a > minAlpha;
17
18
  this.offset = 4;
18
19
  }
19
20
  load(data) {
package/umd/index.js CHANGED
@@ -13,12 +13,11 @@
13
13
  const CanvasMask_js_1 = require("./Options/Classes/CanvasMask.js");
14
14
  const CanvasMaskInstance_js_1 = require("./CanvasMaskInstance.js");
15
15
  class CanvasMaskPlugin {
16
- constructor(engine) {
16
+ constructor() {
17
17
  this.id = "canvasMask";
18
- this._engine = engine;
19
18
  }
20
19
  getPlugin(container) {
21
- return new CanvasMaskInstance_js_1.CanvasMaskInstance(container, this._engine);
20
+ return new CanvasMaskInstance_js_1.CanvasMaskInstance(container);
22
21
  }
23
22
  loadOptions(options, source) {
24
23
  if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
@@ -35,7 +34,7 @@
35
34
  }
36
35
  }
37
36
  async function loadCanvasMaskPlugin(engine, refresh = true) {
38
- await engine.addPlugin(new CanvasMaskPlugin(engine), refresh);
37
+ await engine.addPlugin(new CanvasMaskPlugin(), refresh);
39
38
  }
40
39
  exports.loadCanvasMaskPlugin = loadCanvasMaskPlugin;
41
40
  });
package/umd/utils.js CHANGED
@@ -11,15 +11,19 @@
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.getTextData = exports.getImageData = exports.getCanvasImageData = exports.addParticlesFromCanvasPixels = void 0;
13
13
  const engine_1 = require("@tsparticles/engine");
14
+ const half = 0.5, origin = {
15
+ x: 0,
16
+ y: 0,
17
+ }, defaultWidth = 0;
14
18
  function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
15
19
  const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
16
20
  let selectedPixels = 0;
17
21
  const positionOffset = {
18
- x: (canvasSize.width * position.x) / 100 - (width * scale) / 2,
19
- y: (canvasSize.height * position.y) / 100 - (height * scale) / 2,
22
+ x: (canvasSize.width * position.x) / engine_1.percentDenominator - width * scale * half,
23
+ y: (canvasSize.height * position.y) / engine_1.percentDenominator - height * scale * half,
20
24
  };
21
25
  while (selectedPixels < maxParticles && indexArray.length) {
22
- const nextIndex = indexArray.pop() || 0, pixelPos = {
26
+ const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
23
27
  x: nextIndex % width,
24
28
  y: Math.floor(nextIndex / width),
25
29
  }, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
@@ -46,9 +50,9 @@
46
50
  }
47
51
  exports.addParticlesFromCanvasPixels = addParticlesFromCanvasPixels;
48
52
  function getCanvasImageData(ctx, size, offset, clear = true) {
49
- const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
53
+ const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
50
54
  if (clear) {
51
- ctx.clearRect(0, 0, size.width, size.height);
55
+ ctx.clearRect(origin.x, origin.y, size.width, size.height);
52
56
  }
53
57
  const pixels = [];
54
58
  for (let i = 0; i < imageData.length; i += offset) {
@@ -59,11 +63,17 @@
59
63
  if (!pixels[pos.y]) {
60
64
  pixels[pos.y] = [];
61
65
  }
66
+ const indexesOffset = {
67
+ r: 0,
68
+ g: 1,
69
+ b: 2,
70
+ a: 3,
71
+ }, alphaFactor = 255;
62
72
  pixels[pos.y][pos.x] = {
63
- r: imageData[i],
64
- g: imageData[i + 1],
65
- b: imageData[i + 2],
66
- a: imageData[i + 3] / 255,
73
+ r: imageData[i + indexesOffset.r],
74
+ g: imageData[i + indexesOffset.g],
75
+ b: imageData[i + indexesOffset.b],
76
+ a: imageData[i + indexesOffset.a] / alphaFactor,
67
77
  };
68
78
  }
69
79
  return {
@@ -86,7 +96,7 @@
86
96
  if (!context) {
87
97
  return reject(new Error(`${engine_1.errorPrefix} Could not get canvas context`));
88
98
  }
89
- context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
99
+ context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
90
100
  resolve(getCanvasImageData(context, canvas, offset));
91
101
  };
92
102
  });
@@ -102,14 +112,14 @@
102
112
  const lines = text.split(linesOptions.separator), fontSize = (0, engine_1.isNumber)(font.size) ? `${font.size}px` : font.size, linesData = [];
103
113
  let maxWidth = 0, totalHeight = 0;
104
114
  for (const line of lines) {
105
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
115
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
106
116
  const measure = context.measureText(line), lineData = {
107
117
  measure,
108
118
  text: line,
109
119
  height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
110
120
  width: measure.width,
111
121
  };
112
- maxWidth = Math.max(maxWidth || 0, lineData.width);
122
+ maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
113
123
  totalHeight += lineData.height + linesOptions.spacing;
114
124
  linesData.push(lineData);
115
125
  }
@@ -117,16 +127,17 @@
117
127
  canvas.height = totalHeight;
118
128
  let currentHeight = 0;
119
129
  for (const line of linesData) {
120
- context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
130
+ context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
121
131
  context.fillStyle = color;
122
- context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
132
+ context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
123
133
  currentHeight += line.height + linesOptions.spacing;
124
134
  }
125
135
  return getCanvasImageData(context, canvas, offset);
126
136
  }
127
137
  exports.getTextData = getTextData;
128
138
  function shuffle(array) {
129
- for (let currentIndex = array.length - 1; currentIndex >= 0; currentIndex--) {
139
+ const lengthOffset = 1, minIndex = 0;
140
+ for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
130
141
  const randomIndex = Math.floor((0, engine_1.getRandom)() * currentIndex);
131
142
  [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
132
143
  }