@tsparticles/plugin-canvas-mask 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/browser/CanvasMaskInstance.js +46 -0
  4. package/browser/Options/Classes/CanvasMask.js +54 -0
  5. package/browser/Options/Classes/CanvasMaskOverride.js +17 -0
  6. package/browser/Options/Classes/CanvasMaskPixels.js +27 -0
  7. package/browser/Options/Classes/FontTextMask.js +26 -0
  8. package/browser/Options/Classes/ImageMask.js +13 -0
  9. package/browser/Options/Classes/TextMask.js +23 -0
  10. package/browser/Options/Classes/TextMaskLine.js +17 -0
  11. package/browser/Options/Interfaces/ICanvasMask.js +1 -0
  12. package/browser/Options/Interfaces/ICanvasMaskOverride.js +1 -0
  13. package/browser/Options/Interfaces/ICanvasMaskPixels.js +1 -0
  14. package/browser/Options/Interfaces/IFontTextMask.js +1 -0
  15. package/browser/Options/Interfaces/IImageMask.js +1 -0
  16. package/browser/Options/Interfaces/ITextMask.js +1 -0
  17. package/browser/Options/Interfaces/ITextMaskLine.js +1 -0
  18. package/browser/index.js +29 -0
  19. package/browser/types.js +1 -0
  20. package/browser/utils.js +119 -0
  21. package/cjs/CanvasMaskInstance.js +61 -0
  22. package/cjs/Options/Classes/CanvasMask.js +58 -0
  23. package/cjs/Options/Classes/CanvasMaskOverride.js +21 -0
  24. package/cjs/Options/Classes/CanvasMaskPixels.js +31 -0
  25. package/cjs/Options/Classes/FontTextMask.js +30 -0
  26. package/cjs/Options/Classes/ImageMask.js +17 -0
  27. package/cjs/Options/Classes/TextMask.js +27 -0
  28. package/cjs/Options/Classes/TextMaskLine.js +21 -0
  29. package/cjs/Options/Interfaces/ICanvasMask.js +2 -0
  30. package/cjs/Options/Interfaces/ICanvasMaskOverride.js +2 -0
  31. package/cjs/Options/Interfaces/ICanvasMaskPixels.js +2 -0
  32. package/cjs/Options/Interfaces/IFontTextMask.js +2 -0
  33. package/cjs/Options/Interfaces/IImageMask.js +2 -0
  34. package/cjs/Options/Interfaces/ITextMask.js +2 -0
  35. package/cjs/Options/Interfaces/ITextMaskLine.js +2 -0
  36. package/cjs/index.js +44 -0
  37. package/cjs/types.js +2 -0
  38. package/cjs/utils.js +128 -0
  39. package/esm/CanvasMaskInstance.js +46 -0
  40. package/esm/Options/Classes/CanvasMask.js +54 -0
  41. package/esm/Options/Classes/CanvasMaskOverride.js +17 -0
  42. package/esm/Options/Classes/CanvasMaskPixels.js +27 -0
  43. package/esm/Options/Classes/FontTextMask.js +26 -0
  44. package/esm/Options/Classes/ImageMask.js +13 -0
  45. package/esm/Options/Classes/TextMask.js +23 -0
  46. package/esm/Options/Classes/TextMaskLine.js +17 -0
  47. package/esm/Options/Interfaces/ICanvasMask.js +1 -0
  48. package/esm/Options/Interfaces/ICanvasMaskOverride.js +1 -0
  49. package/esm/Options/Interfaces/ICanvasMaskPixels.js +1 -0
  50. package/esm/Options/Interfaces/IFontTextMask.js +1 -0
  51. package/esm/Options/Interfaces/IImageMask.js +1 -0
  52. package/esm/Options/Interfaces/ITextMask.js +1 -0
  53. package/esm/Options/Interfaces/ITextMaskLine.js +1 -0
  54. package/esm/index.js +29 -0
  55. package/esm/types.js +1 -0
  56. package/esm/utils.js +119 -0
  57. package/package.json +81 -0
  58. package/report.html +39 -0
  59. package/tsparticles.plugin.canvas-mask.js +505 -0
  60. package/tsparticles.plugin.canvas-mask.min.js +2 -0
  61. package/tsparticles.plugin.canvas-mask.min.js.LICENSE.txt +8 -0
  62. package/types/CanvasMaskInstance.d.ts +8 -0
  63. package/types/Options/Classes/CanvasMask.d.ts +19 -0
  64. package/types/Options/Classes/CanvasMaskOverride.d.ts +8 -0
  65. package/types/Options/Classes/CanvasMaskPixels.d.ts +8 -0
  66. package/types/Options/Classes/FontTextMask.d.ts +11 -0
  67. package/types/Options/Classes/ImageMask.d.ts +7 -0
  68. package/types/Options/Classes/TextMask.d.ts +12 -0
  69. package/types/Options/Classes/TextMaskLine.d.ts +8 -0
  70. package/types/Options/Interfaces/ICanvasMask.d.ts +16 -0
  71. package/types/Options/Interfaces/ICanvasMaskOverride.d.ts +4 -0
  72. package/types/Options/Interfaces/ICanvasMaskPixels.d.ts +5 -0
  73. package/types/Options/Interfaces/IFontTextMask.d.ts +7 -0
  74. package/types/Options/Interfaces/IImageMask.d.ts +3 -0
  75. package/types/Options/Interfaces/ITextMask.d.ts +8 -0
  76. package/types/Options/Interfaces/ITextMaskLine.d.ts +4 -0
  77. package/types/index.d.ts +2 -0
  78. package/types/types.d.ts +12 -0
  79. package/types/utils.d.ts +14 -0
  80. package/umd/CanvasMaskInstance.js +60 -0
  81. package/umd/Options/Classes/CanvasMask.js +68 -0
  82. package/umd/Options/Classes/CanvasMaskOverride.js +31 -0
  83. package/umd/Options/Classes/CanvasMaskPixels.js +41 -0
  84. package/umd/Options/Classes/FontTextMask.js +40 -0
  85. package/umd/Options/Classes/ImageMask.js +27 -0
  86. package/umd/Options/Classes/TextMask.js +37 -0
  87. package/umd/Options/Classes/TextMaskLine.js +31 -0
  88. package/umd/Options/Interfaces/ICanvasMask.js +12 -0
  89. package/umd/Options/Interfaces/ICanvasMaskOverride.js +12 -0
  90. package/umd/Options/Interfaces/ICanvasMaskPixels.js +12 -0
  91. package/umd/Options/Interfaces/IFontTextMask.js +12 -0
  92. package/umd/Options/Interfaces/IImageMask.js +12 -0
  93. package/umd/Options/Interfaces/ITextMask.js +12 -0
  94. package/umd/Options/Interfaces/ITextMaskLine.js +12 -0
  95. package/umd/index.js +43 -0
  96. package/umd/types.js +12 -0
  97. package/umd/utils.js +138 -0
@@ -0,0 +1,505 @@
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.0.0-alpha.0
8
+ */
9
+ (function webpackUniversalModuleDefinition(root, factory) {
10
+ if(typeof exports === 'object' && typeof module === 'object')
11
+ module.exports = factory(require("@tsparticles/engine"));
12
+ else if(typeof define === 'function' && define.amd)
13
+ define(["@tsparticles/engine"], factory);
14
+ else {
15
+ var a = typeof exports === 'object' ? factory(require("@tsparticles/engine")) : factory(root["window"]);
16
+ for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
17
+ }
18
+ })(this, (__WEBPACK_EXTERNAL_MODULE__533__) => {
19
+ return /******/ (() => { // webpackBootstrap
20
+ /******/ "use strict";
21
+ /******/ var __webpack_modules__ = ({
22
+
23
+ /***/ 533:
24
+ /***/ ((module) => {
25
+
26
+ module.exports = __WEBPACK_EXTERNAL_MODULE__533__;
27
+
28
+ /***/ })
29
+
30
+ /******/ });
31
+ /************************************************************************/
32
+ /******/ // The module cache
33
+ /******/ var __webpack_module_cache__ = {};
34
+ /******/
35
+ /******/ // The require function
36
+ /******/ function __webpack_require__(moduleId) {
37
+ /******/ // Check if module is in cache
38
+ /******/ var cachedModule = __webpack_module_cache__[moduleId];
39
+ /******/ if (cachedModule !== undefined) {
40
+ /******/ return cachedModule.exports;
41
+ /******/ }
42
+ /******/ // Create a new module (and put it into the cache)
43
+ /******/ var module = __webpack_module_cache__[moduleId] = {
44
+ /******/ // no module.id needed
45
+ /******/ // no module.loaded needed
46
+ /******/ exports: {}
47
+ /******/ };
48
+ /******/
49
+ /******/ // Execute the module function
50
+ /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
51
+ /******/
52
+ /******/ // Return the exports of the module
53
+ /******/ return module.exports;
54
+ /******/ }
55
+ /******/
56
+ /************************************************************************/
57
+ /******/ /* webpack/runtime/define property getters */
58
+ /******/ (() => {
59
+ /******/ // define getter functions for harmony exports
60
+ /******/ __webpack_require__.d = (exports, definition) => {
61
+ /******/ for(var key in definition) {
62
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
63
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
64
+ /******/ }
65
+ /******/ }
66
+ /******/ };
67
+ /******/ })();
68
+ /******/
69
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
70
+ /******/ (() => {
71
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
72
+ /******/ })();
73
+ /******/
74
+ /******/ /* webpack/runtime/make namespace object */
75
+ /******/ (() => {
76
+ /******/ // define __esModule on exports
77
+ /******/ __webpack_require__.r = (exports) => {
78
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
79
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
80
+ /******/ }
81
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
82
+ /******/ };
83
+ /******/ })();
84
+ /******/
85
+ /************************************************************************/
86
+ var __webpack_exports__ = {};
87
+ // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
88
+ (() => {
89
+ // ESM COMPAT FLAG
90
+ __webpack_require__.r(__webpack_exports__);
91
+
92
+ // EXPORTS
93
+ __webpack_require__.d(__webpack_exports__, {
94
+ "loadCanvasMaskPlugin": () => (/* binding */ loadCanvasMaskPlugin)
95
+ });
96
+
97
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/CanvasMaskOverride.js
98
+ class CanvasMaskOverride {
99
+ constructor() {
100
+ this.color = true;
101
+ this.opacity = false;
102
+ }
103
+ load(data) {
104
+ if (!data) {
105
+ return;
106
+ }
107
+ if (data.color !== undefined) {
108
+ this.color = data.color;
109
+ }
110
+ if (data.opacity !== undefined) {
111
+ this.opacity = data.opacity;
112
+ }
113
+ }
114
+ }
115
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/CanvasMaskPixels.js
116
+ class CanvasMaskPixels {
117
+ constructor() {
118
+ this.filter = pixel => pixel.a > 0;
119
+ this.offset = 4;
120
+ }
121
+ load(data) {
122
+ if (!data) {
123
+ return;
124
+ }
125
+ if (data.filter !== undefined) {
126
+ if (typeof data.filter === "string") {
127
+ if (Object.hasOwn(window, data.filter)) {
128
+ const filter = window[data.filter];
129
+ if (typeof filter === "function") {
130
+ this.filter = filter;
131
+ }
132
+ }
133
+ } else {
134
+ this.filter = data.filter;
135
+ }
136
+ }
137
+ if (data.offset !== undefined) {
138
+ this.offset = data.offset;
139
+ }
140
+ }
141
+ }
142
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/ImageMask.js
143
+ class ImageMask {
144
+ constructor() {
145
+ this.src = "";
146
+ }
147
+ load(data) {
148
+ if (!data) {
149
+ return;
150
+ }
151
+ if (data.src !== undefined) {
152
+ this.src = data.src;
153
+ }
154
+ }
155
+ }
156
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/FontTextMask.js
157
+ class FontTextMask {
158
+ constructor() {
159
+ this.family = "sans-serif";
160
+ this.size = 100;
161
+ }
162
+ load(data) {
163
+ if (!data) {
164
+ return;
165
+ }
166
+ if (data.family !== undefined) {
167
+ this.family = data.family;
168
+ }
169
+ if (data.size !== undefined) {
170
+ this.size = data.size;
171
+ }
172
+ if (data.style !== undefined) {
173
+ this.style = data.style;
174
+ }
175
+ if (data.variant !== undefined) {
176
+ this.variant = data.variant;
177
+ }
178
+ if (data.weight !== undefined) {
179
+ this.weight = data.weight;
180
+ }
181
+ }
182
+ }
183
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/TextMaskLine.js
184
+ class TextMaskLine {
185
+ constructor() {
186
+ this.separator = "\n";
187
+ this.spacing = 10;
188
+ }
189
+ load(data) {
190
+ if (!data) {
191
+ return;
192
+ }
193
+ if (data.separator !== undefined) {
194
+ this.separator = data.separator;
195
+ }
196
+ if (data.spacing !== undefined) {
197
+ this.spacing = data.spacing;
198
+ }
199
+ }
200
+ }
201
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/TextMask.js
202
+
203
+
204
+ class TextMask {
205
+ constructor() {
206
+ this.color = "#000000";
207
+ this.font = new FontTextMask();
208
+ this.lines = new TextMaskLine();
209
+ this.text = "";
210
+ }
211
+ load(data) {
212
+ if (!data) {
213
+ return;
214
+ }
215
+ if (data.color !== undefined) {
216
+ this.color = data.color;
217
+ }
218
+ this.font.load(data.font);
219
+ this.lines.load(data.lines);
220
+ if (data.text !== undefined) {
221
+ this.text = data.text;
222
+ }
223
+ }
224
+ }
225
+ ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/CanvasMask.js
226
+
227
+
228
+
229
+
230
+ class CanvasMask {
231
+ constructor() {
232
+ this.enable = false;
233
+ this.override = new CanvasMaskOverride();
234
+ this.pixels = new CanvasMaskPixels();
235
+ this.position = {
236
+ x: 50,
237
+ y: 50
238
+ };
239
+ this.scale = 1;
240
+ }
241
+ load(data) {
242
+ var _a, _b;
243
+ if (!data) {
244
+ return;
245
+ }
246
+ if (data.element !== undefined && data.element instanceof HTMLCanvasElement) {
247
+ this.element = data.element;
248
+ }
249
+ if (data.enable !== undefined) {
250
+ this.enable = data.enable;
251
+ }
252
+ if (data.image) {
253
+ if (!this.image) {
254
+ this.image = new ImageMask();
255
+ }
256
+ this.image.load(data.image);
257
+ }
258
+ this.pixels.load(data.pixels);
259
+ if (data.position) {
260
+ this.position = {
261
+ x: (_a = data.position.x) !== null && _a !== void 0 ? _a : this.position.x,
262
+ y: (_b = data.position.y) !== null && _b !== void 0 ? _b : this.position.y
263
+ };
264
+ }
265
+ this.override.load(data.override);
266
+ if (data.scale !== undefined) {
267
+ this.scale = data.scale;
268
+ }
269
+ if (data.selector !== undefined) {
270
+ this.selector = data.selector;
271
+ }
272
+ if (data.text) {
273
+ if (!this.text) {
274
+ this.text = new TextMask();
275
+ }
276
+ this.text.load(data.text);
277
+ }
278
+ }
279
+ }
280
+ // EXTERNAL MODULE: external {"commonjs":"@tsparticles/engine","commonjs2":"@tsparticles/engine","amd":"@tsparticles/engine","root":"window"}
281
+ var engine_root_window_ = __webpack_require__(533);
282
+ ;// CONCATENATED MODULE: ./dist/browser/utils.js
283
+
284
+ function shuffle(array) {
285
+ for (let currentIndex = array.length - 1; currentIndex >= 0; currentIndex--) {
286
+ const randomIndex = Math.floor((0,engine_root_window_.getRandom)() * currentIndex);
287
+ [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
288
+ }
289
+ return array;
290
+ }
291
+ function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
292
+ const {
293
+ height,
294
+ width
295
+ } = data,
296
+ numPixels = height * width,
297
+ indexArray = shuffle(range(numPixels)),
298
+ maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value),
299
+ canvasSize = container.canvas.size;
300
+ let selectedPixels = 0;
301
+ const positionOffset = {
302
+ x: canvasSize.width * position.x / 100 - width * scale / 2,
303
+ y: canvasSize.height * position.y / 100 - height * scale / 2
304
+ };
305
+ while (selectedPixels < maxParticles && indexArray.length) {
306
+ const nextIndex = indexArray.pop() || 0,
307
+ pixelPos = {
308
+ x: nextIndex % width,
309
+ y: Math.floor(nextIndex / width)
310
+ },
311
+ pixel = data.pixels[pixelPos.y][pixelPos.x],
312
+ shouldCreateParticle = filter(pixel);
313
+ if (shouldCreateParticle) {
314
+ const pos = {
315
+ x: pixelPos.x * scale + positionOffset.x,
316
+ y: pixelPos.y * scale + positionOffset.y
317
+ };
318
+ const pOptions = {};
319
+ if (override.color) {
320
+ pOptions.color = {
321
+ value: pixel
322
+ };
323
+ }
324
+ if (override.opacity) {
325
+ pOptions.opacity = {
326
+ value: pixel.a
327
+ };
328
+ }
329
+ container.particles.addParticle(pos, pOptions);
330
+ selectedPixels++;
331
+ }
332
+ }
333
+ }
334
+ function getCanvasImageData(ctx, size, offset, clear = true) {
335
+ const imageData = ctx.getImageData(0, 0, size.width, size.height).data;
336
+ if (clear) {
337
+ ctx.clearRect(0, 0, size.width, size.height);
338
+ }
339
+ const pixels = [];
340
+ for (let i = 0; i < imageData.length; i += offset) {
341
+ const idx = i / offset,
342
+ pos = {
343
+ x: idx % size.width,
344
+ y: Math.floor(idx / size.width)
345
+ };
346
+ if (!pixels[pos.y]) {
347
+ pixels[pos.y] = [];
348
+ }
349
+ pixels[pos.y][pos.x] = {
350
+ r: imageData[i],
351
+ g: imageData[i + 1],
352
+ b: imageData[i + 2],
353
+ a: imageData[i + 3] / 255
354
+ };
355
+ }
356
+ return {
357
+ pixels,
358
+ width: Math.min(...pixels.map(row => row.length)),
359
+ height: pixels.length
360
+ };
361
+ }
362
+ function getImageData(src, offset) {
363
+ const image = new Image();
364
+ image.crossOrigin = "Anonymous";
365
+ const p = new Promise((resolve, reject) => {
366
+ image.onerror = reject;
367
+ image.onload = () => {
368
+ const canvas = document.createElement("canvas");
369
+ canvas.width = image.width;
370
+ canvas.height = image.height;
371
+ const context = canvas.getContext("2d");
372
+ if (!context) {
373
+ return reject(new Error("Could not get canvas context"));
374
+ }
375
+ context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
376
+ resolve(getCanvasImageData(context, canvas, offset));
377
+ };
378
+ });
379
+ image.src = src;
380
+ return p;
381
+ }
382
+ function getTextData(textOptions, offset) {
383
+ const canvas = document.createElement("canvas"),
384
+ context = canvas.getContext("2d"),
385
+ {
386
+ font,
387
+ text,
388
+ lines: linesOptions,
389
+ color
390
+ } = textOptions;
391
+ if (!text || !context) {
392
+ return;
393
+ }
394
+ const lines = text.split(linesOptions.separator),
395
+ fontSize = typeof font.size === "number" ? `${font.size}px` : font.size,
396
+ linesData = [];
397
+ let maxWidth = 0,
398
+ totalHeight = 0;
399
+ for (const line of lines) {
400
+ context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
401
+ const measure = context.measureText(line),
402
+ lineData = {
403
+ measure,
404
+ text: line,
405
+ height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
406
+ width: measure.width
407
+ };
408
+ maxWidth = Math.max(maxWidth || 0, lineData.width);
409
+ totalHeight += lineData.height + linesOptions.spacing;
410
+ linesData.push(lineData);
411
+ }
412
+ canvas.width = maxWidth;
413
+ canvas.height = totalHeight;
414
+ let currentHeight = 0;
415
+ for (const line of linesData) {
416
+ context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
417
+ context.fillStyle = color;
418
+ context.fillText(line.text, 0, currentHeight + line.measure.actualBoundingBoxAscent);
419
+ currentHeight += line.height + linesOptions.spacing;
420
+ }
421
+ return getCanvasImageData(context, canvas, offset);
422
+ }
423
+ const range = n => [...Array(n).keys()];
424
+ ;// CONCATENATED MODULE: ./dist/browser/CanvasMaskInstance.js
425
+
426
+ class CanvasMaskInstance {
427
+ constructor(container, engine) {
428
+ this._container = container;
429
+ this._engine = engine;
430
+ }
431
+ async init() {
432
+ const container = this._container,
433
+ options = container.actualOptions.canvasMask;
434
+ if (!(options === null || options === void 0 ? void 0 : options.enable)) {
435
+ return;
436
+ }
437
+ let pixelData = {
438
+ pixels: [],
439
+ height: 0,
440
+ width: 0
441
+ };
442
+ const offset = options.pixels.offset;
443
+ if (options.image) {
444
+ const url = options.image.src;
445
+ if (!url) {
446
+ return;
447
+ }
448
+ pixelData = await getImageData(url, offset);
449
+ } else if (options.text) {
450
+ const textOptions = options.text;
451
+ const data = getTextData(textOptions, offset);
452
+ if (!data) {
453
+ return;
454
+ }
455
+ pixelData = data;
456
+ } else if (options.element || options.selector) {
457
+ const canvas = options.element || options.selector && document.querySelector(options.selector);
458
+ if (!canvas) {
459
+ return;
460
+ }
461
+ const context = canvas.getContext("2d");
462
+ if (!context) {
463
+ return;
464
+ }
465
+ pixelData = getCanvasImageData(context, canvas, offset);
466
+ }
467
+ addParticlesFromCanvasPixels(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);
468
+ }
469
+ }
470
+ ;// CONCATENATED MODULE: ./dist/browser/index.js
471
+
472
+
473
+ class CanvasMaskPlugin {
474
+ constructor(engine) {
475
+ this.id = "canvasMask";
476
+ this._engine = engine;
477
+ }
478
+ getPlugin(container) {
479
+ return new CanvasMaskInstance(container, this._engine);
480
+ }
481
+ loadOptions(options, source) {
482
+ if (!this.needsPlugin(source)) {
483
+ return;
484
+ }
485
+ let canvasMaskOptions = options.canvasMask;
486
+ if ((canvasMaskOptions === null || canvasMaskOptions === void 0 ? void 0 : canvasMaskOptions.load) === undefined) {
487
+ options.canvasMask = canvasMaskOptions = new CanvasMask();
488
+ }
489
+ canvasMaskOptions.load(source === null || source === void 0 ? void 0 : source.canvasMask);
490
+ }
491
+ needsPlugin(options) {
492
+ var _a, _b;
493
+ return (_b = (_a = options === null || options === void 0 ? void 0 : options.canvasMask) === null || _a === void 0 ? void 0 : _a.enable) !== null && _b !== void 0 ? _b : false;
494
+ }
495
+ }
496
+ async function loadCanvasMaskPlugin(engine) {
497
+ const plugin = new CanvasMaskPlugin(engine);
498
+ await engine.addPlugin(plugin);
499
+ }
500
+ })();
501
+
502
+ /******/ return __webpack_exports__;
503
+ /******/ })()
504
+ ;
505
+ });
@@ -0,0 +1,2 @@
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 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:()=>g});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))}}class e{constructor(){this.filter=t=>t.a>0,this.offset=4}load(t){if(t){if(void 0!==t.filter)if("string"==typeof t.filter){if(Object.hasOwn(window,t.filter)){const e=window[t.filter];"function"==typeof e&&(this.filter=e)}}else this.filter=t.filter;void 0!==t.offset&&(this.offset=t.offset)}}}class i{constructor(){this.src=""}load(t){t&&void 0!==t.src&&(this.src=t.src)}}class n{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 r{constructor(){this.color="#000000",this.font=new n,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 e,this.position={x:50,y:50},this.scale=1}load(t){var e,o;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 i),this.image.load(t.image)),this.pixels.load(t.pixels),t.position&&(this.position={x:null!==(e=t.position.x)&&void 0!==e?e:this.position.x,y:null!==(o=t.position.y)&&void 0!==o?o: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 r),this.text.load(t.text)))}}var c=o(533);function h(t,e,i,o,s,n){const{height:a,width:r}=e,l=a*r,h=function(t){for(let e=t.length-1;e>=0;e--){const i=Math.floor((0,c.getRandom)()*e);[t[e],t[i]]=[t[i],t[e]]}return t}(f(l)),d=Math.min(l,t.actualOptions.particles.number.value),u=t.canvas.size;let p=0;const g=u.width*i.x/100-r*o/2,v=u.height*i.y/100-a*o/2;for(;p<d&&h.length;){const i=h.pop()||0,a={x:i%r,y:Math.floor(i/r)},l=e.pixels[a.y][a.x];if(n(l)){const e={x:a.x*o+g,y:a.y*o+v},i={};s.color&&(i.color={value:l}),s.opacity&&(i.opacity={value:l.a}),t.particles.addParticle(e,i),p++}}}function d(t,e,i,o=!0){const s=t.getImageData(0,0,e.width,e.height).data;o&&t.clearRect(0,0,e.width,e.height);const n=[];for(let t=0;t<s.length;t+=i){const o=t/i,a={x:o%e.width,y:Math.floor(o/e.width)};n[a.y]||(n[a.y]=[]),n[a.y][a.x]={r:s[t],g:s[t+1],b:s[t+2],a:s[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,e=t.actualOptions.canvasMask;if(!(null==e?void 0:e.enable))return;let i={pixels:[],height:0,width:0};const o=e.pixels.offset;if(e.image){const t=e.image.src;if(!t)return;i=await function(t,e){const i=new Image;i.crossOrigin="Anonymous";const o=new Promise(((t,o)=>{i.onerror=o,i.onload=()=>{const s=document.createElement("canvas");s.width=i.width,s.height=i.height;const n=s.getContext("2d");if(!n)return o(new Error("Could not get canvas context"));n.drawImage(i,0,0,i.width,i.height,0,0,s.width,s.height),t(d(n,s,e))}}));return i.src=t,o}(t,o)}else if(e.text){const t=function(t,e){const i=document.createElement("canvas"),o=i.getContext("2d"),{font:s,text:n,lines:a,color:r}=t;if(!n||!o)return;const l=n.split(a.separator),c="number"==typeof s.size?`${s.size}px`:s.size,h=[];let f=0,u=0;for(const t of l){o.font=`${s.style||""} ${s.variant||""} ${s.weight||""} ${c} ${s.family}`;const e=o.measureText(t),i={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};f=Math.max(f||0,i.width),u+=i.height+a.spacing,h.push(i)}i.width=f,i.height=u;let p=0;for(const t of h)o.font=`${s.style||""} ${s.variant||""} ${s.weight||""} ${c} ${s.family}`,o.fillStyle=r,o.fillText(t.text,0,p+t.measure.actualBoundingBoxAscent),p+=t.height+a.spacing;return d(o,i,e)}(e.text,o);if(!t)return;i=t}else if(e.element||e.selector){const t=e.element||e.selector&&document.querySelector(e.selector);if(!t)return;const s=t.getContext("2d");if(!s)return;i=d(s,t,o)}h(t,i,e.position,e.scale,e.override,e.pixels.filter)}}class p{constructor(t){this.id="canvasMask",this._engine=t}getPlugin(t){return new u(t,this._engine)}loadOptions(t,e){if(!this.needsPlugin(e))return;let i=t.canvasMask;void 0===(null==i?void 0:i.load)&&(t.canvasMask=i=new l),i.load(null==e?void 0:e.canvasMask)}needsPlugin(t){var e,i;return null!==(i=null===(e=null==t?void 0:t.canvasMask)||void 0===e?void 0:e.enable)&&void 0!==i&&i}}async function g(t){const e=new p(t);await t.addPlugin(e)}})(),s})()));
@@ -0,0 +1,8 @@
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.0.0-alpha.0
8
+ */
@@ -0,0 +1,8 @@
1
+ import type { Engine, IContainerPlugin } from "@tsparticles/engine";
2
+ import type { CanvasMaskContainer } from "./types";
3
+ export declare class CanvasMaskInstance implements IContainerPlugin {
4
+ private readonly _container;
5
+ private readonly _engine;
6
+ constructor(container: CanvasMaskContainer, engine: Engine);
7
+ init(): Promise<void>;
8
+ }
@@ -0,0 +1,19 @@
1
+ import type { ICoordinates, IOptionLoader, RecursivePartial } from "@tsparticles/engine";
2
+ import { CanvasMaskOverride } from "./CanvasMaskOverride";
3
+ import { CanvasMaskPixels } from "./CanvasMaskPixels";
4
+ import type { ICanvasMask } from "../Interfaces/ICanvasMask";
5
+ import { ImageMask } from "./ImageMask";
6
+ import { TextMask } from "./TextMask";
7
+ export declare class CanvasMask implements ICanvasMask, IOptionLoader<ICanvasMask> {
8
+ element?: HTMLCanvasElement;
9
+ enable: boolean;
10
+ image?: ImageMask;
11
+ override: CanvasMaskOverride;
12
+ pixels: CanvasMaskPixels;
13
+ position: ICoordinates;
14
+ scale: number;
15
+ selector?: string;
16
+ text?: TextMask;
17
+ constructor();
18
+ load(data?: RecursivePartial<ICanvasMask>): void;
19
+ }
@@ -0,0 +1,8 @@
1
+ import type { IOptionLoader, RecursivePartial } from "@tsparticles/engine";
2
+ import type { ICanvasMaskOverride } from "../Interfaces/ICanvasMaskOverride";
3
+ export declare class CanvasMaskOverride implements ICanvasMaskOverride, IOptionLoader<ICanvasMaskOverride> {
4
+ color: boolean;
5
+ opacity: boolean;
6
+ constructor();
7
+ load(data?: RecursivePartial<ICanvasMaskOverride>): void;
8
+ }
@@ -0,0 +1,8 @@
1
+ import type { IOptionLoader, IRgba, RecursivePartial } from "@tsparticles/engine";
2
+ import type { ICanvasMaskPixels } from "../Interfaces/ICanvasMaskPixels";
3
+ export declare class CanvasMaskPixels implements ICanvasMaskPixels, IOptionLoader<ICanvasMaskPixels> {
4
+ filter: (pixel: IRgba) => boolean;
5
+ offset: number;
6
+ constructor();
7
+ load(data?: RecursivePartial<ICanvasMaskPixels> | undefined): void;
8
+ }
@@ -0,0 +1,11 @@
1
+ import type { IOptionLoader, RecursivePartial } from "@tsparticles/engine";
2
+ import type { IFontTextMask } from "../Interfaces/IFontTextMask";
3
+ export declare class FontTextMask implements IFontTextMask, IOptionLoader<IFontTextMask> {
4
+ family: string;
5
+ size: string | number;
6
+ style?: string;
7
+ variant?: string;
8
+ weight?: string | number;
9
+ constructor();
10
+ load(data?: RecursivePartial<IFontTextMask> | undefined): void;
11
+ }
@@ -0,0 +1,7 @@
1
+ import type { IOptionLoader, RecursivePartial } from "@tsparticles/engine";
2
+ import type { IImageMask } from "../Interfaces/IImageMask";
3
+ export declare class ImageMask implements IImageMask, IOptionLoader<IImageMask> {
4
+ src: string;
5
+ constructor();
6
+ load(data?: RecursivePartial<IImageMask>): void;
7
+ }
@@ -0,0 +1,12 @@
1
+ import type { IOptionLoader, RecursivePartial } from "@tsparticles/engine";
2
+ import { FontTextMask } from "./FontTextMask";
3
+ import type { ITextMask } from "../Interfaces/ITextMask";
4
+ import { TextMaskLine } from "./TextMaskLine";
5
+ export declare class TextMask implements ITextMask, IOptionLoader<ITextMask> {
6
+ color: string;
7
+ font: FontTextMask;
8
+ lines: TextMaskLine;
9
+ text: string;
10
+ constructor();
11
+ load(data?: RecursivePartial<ITextMask>): void;
12
+ }
@@ -0,0 +1,8 @@
1
+ import type { IOptionLoader, RecursivePartial } from "@tsparticles/engine";
2
+ import type { ITextMaskLine } from "../Interfaces/ITextMaskLine";
3
+ export declare class TextMaskLine implements ITextMaskLine, IOptionLoader<ITextMaskLine> {
4
+ separator: string;
5
+ spacing: number;
6
+ constructor();
7
+ load(data?: RecursivePartial<ITextMaskLine> | undefined): void;
8
+ }
@@ -0,0 +1,16 @@
1
+ import type { ICanvasMaskOverride } from "./ICanvasMaskOverride";
2
+ import type { ICanvasMaskPixels } from "./ICanvasMaskPixels";
3
+ import type { ICoordinates } from "@tsparticles/engine";
4
+ import type { IImageMask } from "./IImageMask";
5
+ import type { ITextMask } from "./ITextMask";
6
+ export interface ICanvasMask {
7
+ element?: HTMLCanvasElement;
8
+ enable: boolean;
9
+ image?: IImageMask;
10
+ override: ICanvasMaskOverride;
11
+ pixels: ICanvasMaskPixels;
12
+ position: ICoordinates;
13
+ scale: number;
14
+ selector?: string;
15
+ text?: ITextMask;
16
+ }
@@ -0,0 +1,4 @@
1
+ export interface ICanvasMaskOverride {
2
+ color: boolean;
3
+ opacity: boolean;
4
+ }
@@ -0,0 +1,5 @@
1
+ import type { IRgba } from "@tsparticles/engine";
2
+ export interface ICanvasMaskPixels {
3
+ filter: string | ((pixel: IRgba) => boolean);
4
+ offset: number;
5
+ }
@@ -0,0 +1,7 @@
1
+ export interface IFontTextMask {
2
+ family: string;
3
+ size: number | string;
4
+ style?: string;
5
+ variant?: string;
6
+ weight?: number | string;
7
+ }
@@ -0,0 +1,3 @@
1
+ export interface IImageMask {
2
+ src: string;
3
+ }
@@ -0,0 +1,8 @@
1
+ import type { IFontTextMask } from "./IFontTextMask";
2
+ import type { ITextMaskLine } from "./ITextMaskLine";
3
+ export interface ITextMask {
4
+ color: string;
5
+ font: IFontTextMask;
6
+ lines: ITextMaskLine;
7
+ text: string;
8
+ }
@@ -0,0 +1,4 @@
1
+ export interface ITextMaskLine {
2
+ separator: string;
3
+ spacing: number;
4
+ }
@@ -0,0 +1,2 @@
1
+ import type { Engine } from "@tsparticles/engine";
2
+ export declare function loadCanvasMaskPlugin(engine: Engine): Promise<void>;