@tsparticles/plugin-canvas-mask 3.0.3 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/262.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 262.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_canvas_mask=this.webpackChunk_tsparticles_plugin_canvas_mask||[]).push([[262],{262:(s,i,t)=>{t.d(i,{CanvasMaskPlugin:()=>d});class e{constructor(){this.color=!0,this.opacity=!1}load(s){s&&(void 0!==s.color&&(this.color=s.color),void 0!==s.opacity&&(this.opacity=s.opacity))}}var o=t(533);class a{constructor(){this.filter=s=>s.a>0,this.offset=4}load(s){if(s){if(void 0!==s.filter)if((0,o.isString)(s.filter)){if(Object.hasOwn(window,s.filter)){const i=window[s.filter];(0,o.isFunction)(i)&&(this.filter=i)}}else this.filter=s.filter;void 0!==s.offset&&(this.offset=s.offset)}}}class n{constructor(){this.src=""}load(s){s&&void 0!==s.src&&(this.src=s.src)}}class l{constructor(){this.family="sans-serif",this.size=100}load(s){s&&(void 0!==s.family&&(this.family=s.family),void 0!==s.size&&(this.size=s.size),void 0!==s.style&&(this.style=s.style),void 0!==s.variant&&(this.variant=s.variant),void 0!==s.weight&&(this.weight=s.weight))}}class c{constructor(){this.separator="\n",this.spacing=10}load(s){s&&(void 0!==s.separator&&(this.separator=s.separator),void 0!==s.spacing&&(this.spacing=s.spacing))}}class r{constructor(){this.color="#000000",this.font=new l,this.lines=new c,this.text=""}load(s){s&&(void 0!==s.color&&(this.color=s.color),this.font.load(s.font),this.lines.load(s.lines),void 0!==s.text&&(this.text=s.text))}}class h{constructor(){this.enable=!1,this.override=new e,this.pixels=new a,this.position={x:50,y:50},this.scale=1}load(s){s&&(void 0!==s.element&&s.element instanceof HTMLCanvasElement&&(this.element=s.element),void 0!==s.enable&&(this.enable=s.enable),s.image&&(this.image||(this.image=new n),this.image.load(s.image)),this.pixels.load(s.pixels),s.position&&(this.position={x:s.position.x??this.position.x,y:s.position.y??this.position.y}),this.override.load(s.override),void 0!==s.scale&&(this.scale=s.scale),void 0!==s.selector&&(this.selector=s.selector),s.text&&(this.text||(this.text=new r),this.text.load(s.text)))}}class d{constructor(){this.id="canvasMask"}async getPlugin(s){const{CanvasMaskInstance:i}=await t.e(73).then(t.bind(t,73));return new i(s)}loadOptions(s,i){if(!this.needsPlugin(s)&&!this.needsPlugin(i))return;let t=s.canvasMask;void 0===t?.load&&(s.canvasMask=t=new h),t.load(i?.canvasMask)}needsPlugin(s){return s?.canvasMask?.enable??!1}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Canvas Mask Plugin v3.2.0 by Matteo Bruni */
package/73.min.js ADDED
@@ -0,0 +1,2 @@
1
+ /*! For license information please see 73.min.js.LICENSE.txt */
2
+ (this.webpackChunk_tsparticles_plugin_canvas_mask=this.webpackChunk_tsparticles_plugin_canvas_mask||[]).push([[73],{73:(t,e,n)=>{n.d(e,{CanvasMaskInstance:()=>r});var i=n(533);const o={x:0,y:0};async function a(t,e,n,o,a,s){const{height:r,width:h}=e,l=r*h,u=function(t){const e=1,n=0;for(let o=t.length-e;o>=n;o--){const e=Math.floor((0,i.getRandom)()*o);[t[o],t[e]]=[t[e],t[o]]}return t}(c(l)),g=Math.min(l,t.actualOptions.particles.number.value),f=t.canvas.size;let x=0;const d=f.width*n.x/i.percentDenominator-h*o*.5,m=f.height*n.y/i.percentDenominator-r*o*.5;for(;x<g&&u.length;){const n=0,i=u.pop()??n,c={x:i%h,y:Math.floor(i/h)},r=e.pixels[c.y][c.x];if(!s(r))continue;const l={x:c.x*o+d,y:c.y*o+m},g={};a.color&&(g.color={value:r}),a.opacity&&(g.opacity={value:r.a}),await t.particles.addParticle(l,g),x++}}function s(t,e,n,i=!0){const a=t.getImageData(o.x,o.y,e.width,e.height).data;i&&t.clearRect(o.x,o.y,e.width,e.height);const s=[];for(let t=0;t<a.length;t+=n){const i=t/n,o={x:i%e.width,y:Math.floor(i/e.width)};s[o.y]||(s[o.y]=[]);const c={r:0,g:1,b:2,a:3},r=255;s[o.y][o.x]={r:a[t+c.r],g:a[t+c.g],b:a[t+c.b],a:a[t+c.a]/r}}return{pixels:s,width:Math.min(...s.map((t=>t.length))),height:s.length}}const c=t=>[...Array(t).keys()];class r{constructor(t){this._container=t}async init(){const t=this._container,e=t.actualOptions.canvasMask;if(!e?.enable)return;let n={pixels:[],height:0,width:0};const c=e.pixels.offset;if(e.image){const t=e.image.src;if(!t)return;n=await function(t,e){const n=new Image;n.crossOrigin="Anonymous";const a=new Promise(((t,a)=>{n.onerror=a,n.onload=()=>{const c=document.createElement("canvas");c.width=n.width,c.height=n.height;const r=c.getContext("2d");if(!r)return a(new Error(`${i.errorPrefix} Could not get canvas context`));r.drawImage(n,o.x,o.y,n.width,n.height,o.x,o.y,c.width,c.height),t(s(r,c,e))}}));return n.src=t,a}(t,c)}else if(e.text){const t=function(t,e){const n=document.createElement("canvas"),a=n.getContext("2d"),{font:c,text:r,lines:h,color:l}=t;if(!r||!a)return;const u=r.split(h.separator),g=(0,i.isNumber)(c.size)?`${c.size}px`:c.size,f=[];let x=0,d=0;for(const t of u){a.font=`${c.style??""} ${c.variant??""} ${c.weight??""} ${g} ${c.family}`;const e=a.measureText(t),n={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};x=Math.max(x||0,n.width),d+=n.height+h.spacing,f.push(n)}n.width=x,n.height=d;let m=0;for(const t of f)a.font=`${c.style??""} ${c.variant??""} ${c.weight??""} ${g} ${c.family}`,a.fillStyle=l,a.fillText(t.text,o.x,m+t.measure.actualBoundingBoxAscent),m+=t.height+h.spacing;return s(a,n,e)}(e.text,c);if(!t)return;n=t}else if(e.element??e.selector){const t=e.element??(e.selector&&document.querySelector(e.selector));if(!t)return;const i=t.getContext("2d");if(!i)return;n=s(i,t,c)}await a(t,n,e.position,e.scale,e.override,e.pixels.filter)}}}}]);
@@ -0,0 +1 @@
1
+ /*! tsParticles Canvas Mask Plugin v3.2.0 by Matteo Bruni */
@@ -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
  }
@@ -41,6 +40,6 @@ export class CanvasMaskInstance {
41
40
  }
42
41
  pixelData = getCanvasImageData(context, canvas, offset);
43
42
  }
44
- addParticlesFromCanvasPixels(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);
43
+ await addParticlesFromCanvasPixels(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);
45
44
  }
46
45
  }
@@ -0,0 +1,23 @@
1
+ import { CanvasMask } from "./Options/Classes/CanvasMask.js";
2
+ export class CanvasMaskPlugin {
3
+ constructor() {
4
+ this.id = "canvasMask";
5
+ }
6
+ async getPlugin(container) {
7
+ const { CanvasMaskInstance } = await import("./CanvasMaskInstance.js");
8
+ return new CanvasMaskInstance(container);
9
+ }
10
+ loadOptions(options, source) {
11
+ if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
12
+ return;
13
+ }
14
+ let canvasMaskOptions = options.canvasMask;
15
+ if (canvasMaskOptions?.load === undefined) {
16
+ options.canvasMask = canvasMaskOptions = new CanvasMask();
17
+ }
18
+ canvasMaskOptions.load(source?.canvasMask);
19
+ }
20
+ needsPlugin(options) {
21
+ return options?.canvasMask?.enable ?? false;
22
+ }
23
+ }
@@ -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,27 +1,4 @@
1
- import { CanvasMask } from "./Options/Classes/CanvasMask.js";
2
- import { CanvasMaskInstance } from "./CanvasMaskInstance.js";
3
- class CanvasMaskPlugin {
4
- constructor(engine) {
5
- this.id = "canvasMask";
6
- this._engine = engine;
7
- }
8
- getPlugin(container) {
9
- return new CanvasMaskInstance(container, this._engine);
10
- }
11
- loadOptions(options, source) {
12
- if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
13
- return;
14
- }
15
- let canvasMaskOptions = options.canvasMask;
16
- if (canvasMaskOptions?.load === undefined) {
17
- options.canvasMask = canvasMaskOptions = new CanvasMask();
18
- }
19
- canvasMaskOptions.load(source?.canvasMask);
20
- }
21
- needsPlugin(options) {
22
- return options?.canvasMask?.enable ?? false;
23
- }
24
- }
25
1
  export async function loadCanvasMaskPlugin(engine, refresh = true) {
26
- await engine.addPlugin(new CanvasMaskPlugin(engine), refresh);
2
+ const { CanvasMaskPlugin } = await import("./CanvasMaskPlugin.js");
3
+ await engine.addPlugin(new CanvasMaskPlugin(), refresh);
27
4
  }
package/browser/utils.js CHANGED
@@ -1,13 +1,17 @@
1
- import { errorPrefix, getRandom, isNumber, } from "@tsparticles/engine";
2
- export function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
1
+ import { errorPrefix, getRandom, isNumber, percentDenominator, } from "@tsparticles/engine";
2
+ const half = 0.5, origin = {
3
+ x: 0,
4
+ y: 0,
5
+ }, defaultWidth = 0;
6
+ export async 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);
@@ -28,14 +32,14 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
28
32
  value: pixel.a,
29
33
  };
30
34
  }
31
- container.particles.addParticle(pos, pOptions);
35
+ await container.particles.addParticle(pos, pOptions);
32
36
  selectedPixels++;
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
  }
@@ -44,7 +43,7 @@ class CanvasMaskInstance {
44
43
  }
45
44
  pixelData = (0, utils_js_1.getCanvasImageData)(context, canvas, offset);
46
45
  }
47
- (0, utils_js_1.addParticlesFromCanvasPixels)(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);
46
+ await (0, utils_js_1.addParticlesFromCanvasPixels)(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);
48
47
  }
49
48
  }
50
49
  exports.CanvasMaskInstance = CanvasMaskInstance;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.CanvasMaskPlugin = void 0;
27
+ const CanvasMask_js_1 = require("./Options/Classes/CanvasMask.js");
28
+ class CanvasMaskPlugin {
29
+ constructor() {
30
+ this.id = "canvasMask";
31
+ }
32
+ async getPlugin(container) {
33
+ const { CanvasMaskInstance } = await Promise.resolve().then(() => __importStar(require("./CanvasMaskInstance.js")));
34
+ return new CanvasMaskInstance(container);
35
+ }
36
+ loadOptions(options, source) {
37
+ if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
38
+ return;
39
+ }
40
+ let canvasMaskOptions = options.canvasMask;
41
+ if (canvasMaskOptions?.load === undefined) {
42
+ options.canvasMask = canvasMaskOptions = new CanvasMask_js_1.CanvasMask();
43
+ }
44
+ canvasMaskOptions.load(source?.canvasMask);
45
+ }
46
+ needsPlugin(options) {
47
+ return options?.canvasMask?.enable ?? false;
48
+ }
49
+ }
50
+ exports.CanvasMaskPlugin = CanvasMaskPlugin;
@@ -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
@@ -1,31 +1,31 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.loadCanvasMaskPlugin = void 0;
4
- const CanvasMask_js_1 = require("./Options/Classes/CanvasMask.js");
5
- const CanvasMaskInstance_js_1 = require("./CanvasMaskInstance.js");
6
- class CanvasMaskPlugin {
7
- constructor(engine) {
8
- this.id = "canvasMask";
9
- this._engine = engine;
10
- }
11
- getPlugin(container) {
12
- return new CanvasMaskInstance_js_1.CanvasMaskInstance(container, this._engine);
13
- }
14
- loadOptions(options, source) {
15
- if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
16
- return;
17
- }
18
- let canvasMaskOptions = options.canvasMask;
19
- if (canvasMaskOptions?.load === undefined) {
20
- options.canvasMask = canvasMaskOptions = new CanvasMask_js_1.CanvasMask();
21
- }
22
- canvasMaskOptions.load(source?.canvasMask);
23
- }
24
- needsPlugin(options) {
25
- return options?.canvasMask?.enable ?? false;
26
- }
27
- }
28
27
  async function loadCanvasMaskPlugin(engine, refresh = true) {
29
- await engine.addPlugin(new CanvasMaskPlugin(engine), refresh);
28
+ const { CanvasMaskPlugin } = await Promise.resolve().then(() => __importStar(require("./CanvasMaskPlugin.js")));
29
+ await engine.addPlugin(new CanvasMaskPlugin(), refresh);
30
30
  }
31
31
  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
- function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
5
+ const half = 0.5, origin = {
6
+ x: 0,
7
+ y: 0,
8
+ }, defaultWidth = 0;
9
+ async 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);
@@ -31,15 +35,15 @@ function addParticlesFromCanvasPixels(container, data, position, scale, override
31
35
  value: pixel.a,
32
36
  };
33
37
  }
34
- container.particles.addParticle(pos, pOptions);
38
+ await container.particles.addParticle(pos, pOptions);
35
39
  selectedPixels++;
36
40
  }
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
  }
@@ -0,0 +1,40 @@
1
+ /*!
2
+ * Author : Matteo Bruni
3
+ * MIT license: https://opensource.org/licenses/MIT
4
+ * Demo / Generator : https://particles.js.org/
5
+ * GitHub : https://www.github.com/matteobruni/tsparticles
6
+ * How to use? : Check the GitHub README
7
+ * v3.2.0
8
+ */
9
+ "use strict";
10
+ /*
11
+ * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
12
+ * This devtool is neither made for production nor for readable output files.
13
+ * It uses "eval()" calls to create a separate source file in the browser devtools.
14
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
15
+ * or disable the default devtool with "devtool: false".
16
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
17
+ */
18
+ (this["webpackChunk_tsparticles_plugin_canvas_mask"] = this["webpackChunk_tsparticles_plugin_canvas_mask"] || []).push([["dist_browser_CanvasMaskInstance_js"],{
19
+
20
+ /***/ "./dist/browser/CanvasMaskInstance.js":
21
+ /*!********************************************!*\
22
+ !*** ./dist/browser/CanvasMaskInstance.js ***!
23
+ \********************************************/
24
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
25
+
26
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CanvasMaskInstance: () => (/* binding */ CanvasMaskInstance)\n/* harmony export */ });\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils.js */ \"./dist/browser/utils.js\");\n\nclass CanvasMaskInstance {\n constructor(container) {\n this._container = container;\n }\n async init() {\n const container = this._container,\n options = container.actualOptions.canvasMask;\n if (!options?.enable) {\n return;\n }\n let pixelData = {\n pixels: [],\n height: 0,\n width: 0\n };\n const offset = options.pixels.offset;\n if (options.image) {\n const url = options.image.src;\n if (!url) {\n return;\n }\n pixelData = await (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.getImageData)(url, offset);\n } else if (options.text) {\n const textOptions = options.text;\n const data = (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.getTextData)(textOptions, offset);\n if (!data) {\n return;\n }\n pixelData = data;\n } else if (options.element ?? options.selector) {\n const canvas = options.element ?? (options.selector && document.querySelector(options.selector));\n if (!canvas) {\n return;\n }\n const context = canvas.getContext(\"2d\");\n if (!context) {\n return;\n }\n pixelData = (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.getCanvasImageData)(context, canvas, offset);\n }\n await (0,_utils_js__WEBPACK_IMPORTED_MODULE_0__.addParticlesFromCanvasPixels)(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-canvas-mask/./dist/browser/CanvasMaskInstance.js?");
27
+
28
+ /***/ }),
29
+
30
+ /***/ "./dist/browser/utils.js":
31
+ /*!*******************************!*\
32
+ !*** ./dist/browser/utils.js ***!
33
+ \*******************************/
34
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
35
+
36
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addParticlesFromCanvasPixels: () => (/* binding */ addParticlesFromCanvasPixels),\n/* harmony export */ getCanvasImageData: () => (/* binding */ getCanvasImageData),\n/* harmony export */ getImageData: () => (/* binding */ getImageData),\n/* harmony export */ getTextData: () => (/* binding */ getTextData)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__);\n\nconst half = 0.5,\n origin = {\n x: 0,\n y: 0\n },\n defaultWidth = 0;\nasync function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {\n const {\n height,\n width\n } = data,\n numPixels = height * width,\n indexArray = shuffle(range(numPixels)),\n maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value),\n canvasSize = container.canvas.size;\n let selectedPixels = 0;\n const positionOffset = {\n x: canvasSize.width * position.x / _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.percentDenominator - width * scale * half,\n y: canvasSize.height * position.y / _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.percentDenominator - height * scale * half\n };\n while (selectedPixels < maxParticles && indexArray.length) {\n const defaultIndex = 0,\n nextIndex = indexArray.pop() ?? defaultIndex,\n pixelPos = {\n x: nextIndex % width,\n y: Math.floor(nextIndex / width)\n },\n pixel = data.pixels[pixelPos.y][pixelPos.x],\n shouldCreateParticle = filter(pixel);\n if (!shouldCreateParticle) {\n continue;\n }\n const pos = {\n x: pixelPos.x * scale + positionOffset.x,\n y: pixelPos.y * scale + positionOffset.y\n },\n pOptions = {};\n if (override.color) {\n pOptions.color = {\n value: pixel\n };\n }\n if (override.opacity) {\n pOptions.opacity = {\n value: pixel.a\n };\n }\n await container.particles.addParticle(pos, pOptions);\n selectedPixels++;\n }\n}\nfunction getCanvasImageData(ctx, size, offset, clear = true) {\n const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;\n if (clear) {\n ctx.clearRect(origin.x, origin.y, size.width, size.height);\n }\n const pixels = [];\n for (let i = 0; i < imageData.length; i += offset) {\n const idx = i / offset,\n pos = {\n x: idx % size.width,\n y: Math.floor(idx / size.width)\n };\n if (!pixels[pos.y]) {\n pixels[pos.y] = [];\n }\n const indexesOffset = {\n r: 0,\n g: 1,\n b: 2,\n a: 3\n },\n alphaFactor = 255;\n pixels[pos.y][pos.x] = {\n r: imageData[i + indexesOffset.r],\n g: imageData[i + indexesOffset.g],\n b: imageData[i + indexesOffset.b],\n a: imageData[i + indexesOffset.a] / alphaFactor\n };\n }\n return {\n pixels,\n width: Math.min(...pixels.map(row => row.length)),\n height: pixels.length\n };\n}\nfunction getImageData(src, offset) {\n const image = new Image();\n image.crossOrigin = \"Anonymous\";\n const p = new Promise((resolve, reject) => {\n image.onerror = reject;\n image.onload = () => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = image.width;\n canvas.height = image.height;\n const context = canvas.getContext(\"2d\");\n if (!context) {\n return reject(new Error(`${_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.errorPrefix} Could not get canvas context`));\n }\n context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);\n resolve(getCanvasImageData(context, canvas, offset));\n };\n });\n image.src = src;\n return p;\n}\nfunction getTextData(textOptions, offset) {\n const canvas = document.createElement(\"canvas\"),\n context = canvas.getContext(\"2d\"),\n {\n font,\n text,\n lines: linesOptions,\n color\n } = textOptions;\n if (!text || !context) {\n return;\n }\n const lines = text.split(linesOptions.separator),\n fontSize = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isNumber)(font.size) ? `${font.size}px` : font.size,\n linesData = [];\n let maxWidth = 0,\n totalHeight = 0;\n for (const line of lines) {\n context.font = `${font.style ?? \"\"} ${font.variant ?? \"\"} ${font.weight ?? \"\"} ${fontSize} ${font.family}`;\n const measure = context.measureText(line),\n lineData = {\n measure,\n text: line,\n height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,\n width: measure.width\n };\n maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);\n totalHeight += lineData.height + linesOptions.spacing;\n linesData.push(lineData);\n }\n canvas.width = maxWidth;\n canvas.height = totalHeight;\n let currentHeight = 0;\n for (const line of linesData) {\n context.font = `${font.style ?? \"\"} ${font.variant ?? \"\"} ${font.weight ?? \"\"} ${fontSize} ${font.family}`;\n context.fillStyle = color;\n context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);\n currentHeight += line.height + linesOptions.spacing;\n }\n return getCanvasImageData(context, canvas, offset);\n}\nfunction shuffle(array) {\n const lengthOffset = 1,\n minIndex = 0;\n for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {\n const randomIndex = Math.floor((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRandom)() * currentIndex);\n [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];\n }\n return array;\n}\nconst range = n => [...Array(n).keys()];\n\n//# sourceURL=webpack://@tsparticles/plugin-canvas-mask/./dist/browser/utils.js?");
37
+
38
+ /***/ })
39
+
40
+ }]);