@tsparticles/plugin-canvas-mask 4.0.0-alpha.5 → 4.0.0-beta.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/565.min.js +1 -0
- package/597.min.js +2 -0
- package/browser/CanvasMaskPlugin.js +1 -3
- package/browser/CanvasMaskPluginInstance.js +7 -7
- package/browser/Options/Classes/CanvasMask.js +9 -0
- package/browser/Options/Classes/CanvasMaskOverride.js +2 -0
- package/browser/Options/Classes/CanvasMaskPixels.js +3 -1
- package/browser/Options/Classes/FontTextMask.js +8 -0
- package/browser/Options/Classes/ImageMask.js +1 -0
- package/browser/Options/Classes/TextMask.js +9 -0
- package/browser/Options/Classes/TextMaskLine.js +2 -0
- package/browser/index.js +1 -1
- package/browser/utils.js +6 -89
- package/cjs/CanvasMaskPlugin.js +1 -3
- package/cjs/CanvasMaskPluginInstance.js +7 -7
- package/cjs/Options/Classes/CanvasMask.js +9 -0
- package/cjs/Options/Classes/CanvasMaskOverride.js +2 -0
- package/cjs/Options/Classes/CanvasMaskPixels.js +3 -1
- package/cjs/Options/Classes/FontTextMask.js +8 -0
- package/cjs/Options/Classes/ImageMask.js +1 -0
- package/cjs/Options/Classes/TextMask.js +9 -0
- package/cjs/Options/Classes/TextMaskLine.js +2 -0
- package/cjs/index.js +1 -1
- package/cjs/utils.js +6 -89
- package/dist_browser_CanvasMaskPluginInstance_js.js +3 -3
- package/dist_browser_CanvasMaskPlugin_js.js +9 -9
- package/esm/CanvasMaskPlugin.js +1 -3
- package/esm/CanvasMaskPluginInstance.js +7 -7
- package/esm/Options/Classes/CanvasMask.js +9 -0
- package/esm/Options/Classes/CanvasMaskOverride.js +2 -0
- package/esm/Options/Classes/CanvasMaskPixels.js +3 -1
- package/esm/Options/Classes/FontTextMask.js +8 -0
- package/esm/Options/Classes/ImageMask.js +1 -0
- package/esm/Options/Classes/TextMask.js +9 -0
- package/esm/Options/Classes/TextMaskLine.js +2 -0
- package/esm/index.js +1 -1
- package/esm/utils.js +6 -89
- package/package.json +3 -2
- package/report.html +3 -3
- package/tsparticles.plugin.canvas-mask.js +41 -19
- package/tsparticles.plugin.canvas-mask.min.js +2 -2
- package/types/CanvasMaskPlugin.d.ts +1 -2
- package/types/Options/Classes/FontTextMask.d.ts +3 -3
- package/types/Options/Classes/TextMask.d.ts +1 -0
- package/types/Options/Interfaces/IFontTextMask.d.ts +2 -7
- package/types/Options/Interfaces/ITextMask.d.ts +3 -3
- package/types/Options/Interfaces/ITextMaskLine.d.ts +2 -4
- package/types/utils.d.ts +2 -10
- package/umd/CanvasMaskPlugin.js +1 -3
- package/umd/CanvasMaskPluginInstance.js +9 -9
- package/umd/Options/Classes/CanvasMask.js +9 -0
- package/umd/Options/Classes/CanvasMaskOverride.js +2 -0
- package/umd/Options/Classes/CanvasMaskPixels.js +3 -1
- package/umd/Options/Classes/FontTextMask.js +8 -0
- package/umd/Options/Classes/ImageMask.js +1 -0
- package/umd/Options/Classes/TextMask.js +9 -0
- package/umd/Options/Classes/TextMaskLine.js +2 -0
- package/umd/index.js +1 -1
- package/umd/utils.js +5 -91
- package/722.min.js +0 -2
- package/722.min.js.LICENSE.txt +0 -1
- package/775.min.js +0 -2
- package/775.min.js.LICENSE.txt +0 -1
- package/tsparticles.plugin.canvas-mask.min.js.LICENSE.txt +0 -1
package/565.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(this.webpackChunk_tsparticles_plugin_canvas_mask=this.webpackChunk_tsparticles_plugin_canvas_mask||[]).push([[565],{565(e,t,a){a.d(t,{CanvasMaskPluginInstance:()=>l});var i=a(425),n=a(303);class l{_container;constructor(e){this._container=e}async init(){let e=this._container,t=e.actualOptions.canvasMask;if(!t?.enable)return;let a={pixels:[],height:0,width:0},l=t.pixels.offset;if(t.image){let n=t.image.src;if(!n)return;a=await (0,i.getImageData)(n,l,e.canvas.settings)}else if(t.text){let s=t.text,r=(0,i.getTextData)(s,l,s.fill,e.canvas.settings);if((0,n.isNull)(r))return;a=r}else if(t.element??t.selector){let s=t.element??(t.selector&&(0,n.safeDocument)().querySelector(t.selector));if(!s)return;let r=s.getContext("2d",e.canvas.settings);if(!r)return;a=(0,i.getCanvasImageData)(r,s,l)}!function(e,t,a,i,l,s){let{height:r,width:c}=t,o=r*c,u=function(e){for(let t=e.length-1;t>=0;t--){let a=Math.floor((0,n.getRandom)()*t),i=e[t],l=e[a];l!==i&&void 0!==l&&void 0!==i&&(e[t]=l,e[a]=i)}return e}([...Array(o).keys()]),f=Math.min(o,e.actualOptions.particles.number.value),p=e.canvas.size,h=0,g={x:p.width*a.x/n.percentDenominator-c*i*n.half,y:p.height*a.y/n.percentDenominator-r*i*n.half};for(;h<f&&u.length;){let a=u.pop()??0,n={x:a%c,y:Math.floor(a/c)},r=t.pixels[n.y];if(!r)continue;let o=r[n.x];if(!o||!s(o))continue;let f={x:n.x*i+g.x,y:n.y*i+g.y},p={};l.color&&(p.fill={color:{value:o},enable:!0}),l.opacity&&(p.opacity={value:o.a}),e.particles.addParticle(f,p),h++}}(e,a,t.position,t.scale,t.override,t.pixels.filter)}}}}]);
|
package/597.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";(this.webpackChunk_tsparticles_plugin_canvas_mask=this.webpackChunk_tsparticles_plugin_canvas_mask||[]).push([[597],{597(i,s,t){t.d(s,{CanvasMaskPlugin:()=>d});var e=t(303);class l{color;opacity;constructor(){this.color=!0,this.opacity=!1}load(i){(0,e.isNull)(i)||(void 0!==i.color&&(this.color=i.color),void 0!==i.opacity&&(this.opacity=i.opacity))}}class o{filter;offset;constructor(){this.filter=i=>i.a>0,this.offset=4}load(i){if(!(0,e.isNull)(i)){if(void 0!==i.filter)if((0,e.isString)(i.filter)){if(i.filter in globalThis){let s=globalThis[i.filter];(0,e.isFunction)(s)&&(this.filter=s)}}else this.filter=i.filter;void 0!==i.offset&&(this.offset=i.offset)}}}class a{src;constructor(){this.src=""}load(i){(0,e.isNull)(i)||void 0!==i.src&&(this.src=i.src)}}class n{family;size;style;variant;weight;constructor(){this.family="sans-serif",this.size=100,this.style="",this.variant="",this.weight=""}load(i){(0,e.isNull)(i)||(void 0!==i.family&&(this.family=i.family),void 0!==i.size&&(this.size=i.size),void 0!==i.style&&(this.style=i.style),void 0!==i.variant&&(this.variant=i.variant),void 0!==i.weight&&(this.weight=i.weight))}}class r{separator;spacing;constructor(){this.separator=`
|
|
2
|
+
`,this.spacing=10}load(i){(0,e.isNull)(i)||(void 0!==i.separator&&(this.separator=i.separator),void 0!==i.spacing&&(this.spacing=i.spacing))}}class c{color;fill;font;lines;text;constructor(){this.color="#000000",this.fill=!0,this.font=new n,this.lines=new r,this.text=""}load(i){(0,e.isNull)(i)||(void 0!==i.color&&(this.color=i.color),void 0!==i.fill&&(this.fill=i.fill),this.font.load(i.font),this.lines.load(i.lines),void 0!==i.text&&(this.text=i.text))}}class h{element;enable;image;override;pixels;position;scale;selector;text;constructor(){this.enable=!1,this.override=new l,this.pixels=new o,this.position={x:50,y:50},this.scale=1}load(i){!(0,e.isNull)(i)&&(void 0!==i.element&&i.element instanceof HTMLCanvasElement&&(this.element=i.element),void 0!==i.enable&&(this.enable=i.enable),i.image&&(this.image??=new a,this.image.load(i.image)),this.pixels.load(i.pixels),i.position&&(this.position={x:i.position.x??this.position.x,y:i.position.y??this.position.y}),this.override.load(i.override),void 0!==i.scale&&(this.scale=i.scale),void 0!==i.selector&&(this.selector=i.selector),i.text&&(this.text??=new c,this.text.load(i.text)))}}class d{id="canvas-mask";async getPlugin(i){let{CanvasMaskPluginInstance:s}=await t.e(565).then(t.bind(t,565));return new s(i)}loadOptions(i,s,t){if(!this.needsPlugin(s)&&!this.needsPlugin(t))return;let e=s.canvasMask;e?.load===void 0&&(s.canvasMask=e=new h),e.load(t?.canvasMask)}needsPlugin(i){return i?.canvasMask?.enable??!1}}}}]);
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { CanvasMask } from "./Options/Classes/CanvasMask.js";
|
|
2
2
|
export class CanvasMaskPlugin {
|
|
3
|
-
|
|
4
|
-
this.id = "canvasMask";
|
|
5
|
-
}
|
|
3
|
+
id = "canvas-mask";
|
|
6
4
|
async getPlugin(container) {
|
|
7
5
|
const { CanvasMaskPluginInstance } = await import("./CanvasMaskPluginInstance.js");
|
|
8
6
|
return new CanvasMaskPluginInstance(container);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getCanvasImageData, getImageData, getTextData } from "@tsparticles/canvas-utils";
|
|
2
2
|
import { isNull, safeDocument } from "@tsparticles/engine";
|
|
3
|
+
import { addParticlesFromCanvasPixels } from "./utils.js";
|
|
3
4
|
export class CanvasMaskPluginInstance {
|
|
5
|
+
_container;
|
|
4
6
|
constructor(container) {
|
|
5
7
|
this._container = container;
|
|
6
8
|
}
|
|
@@ -20,23 +22,21 @@ export class CanvasMaskPluginInstance {
|
|
|
20
22
|
if (!url) {
|
|
21
23
|
return;
|
|
22
24
|
}
|
|
23
|
-
pixelData = await getImageData(url, offset);
|
|
25
|
+
pixelData = await getImageData(url, offset, container.canvas.settings);
|
|
24
26
|
}
|
|
25
27
|
else if (options.text) {
|
|
26
|
-
const textOptions = options.text;
|
|
27
|
-
const data = getTextData(textOptions, offset);
|
|
28
|
+
const textOptions = options.text, data = getTextData(textOptions, offset, textOptions.fill, container.canvas.settings);
|
|
28
29
|
if (isNull(data)) {
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
32
|
pixelData = data;
|
|
32
33
|
}
|
|
33
34
|
else if (options.element ?? options.selector) {
|
|
34
|
-
const canvas = options.element ??
|
|
35
|
-
(options.selector && safeDocument().querySelector(options.selector));
|
|
35
|
+
const canvas = options.element ?? (options.selector && safeDocument().querySelector(options.selector));
|
|
36
36
|
if (!canvas) {
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
const context = canvas.getContext("2d");
|
|
39
|
+
const context = canvas.getContext("2d", container.canvas.settings);
|
|
40
40
|
if (!context) {
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
@@ -4,6 +4,15 @@ import { CanvasMaskPixels } from "./CanvasMaskPixels.js";
|
|
|
4
4
|
import { ImageMask } from "./ImageMask.js";
|
|
5
5
|
import { TextMask } from "./TextMask.js";
|
|
6
6
|
export class CanvasMask {
|
|
7
|
+
element;
|
|
8
|
+
enable;
|
|
9
|
+
image;
|
|
10
|
+
override;
|
|
11
|
+
pixels;
|
|
12
|
+
position;
|
|
13
|
+
scale;
|
|
14
|
+
selector;
|
|
15
|
+
text;
|
|
7
16
|
constructor() {
|
|
8
17
|
this.enable = false;
|
|
9
18
|
this.override = new CanvasMaskOverride();
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { isFunction, isNull, isString, } from "@tsparticles/engine";
|
|
2
2
|
const minAlpha = 0;
|
|
3
3
|
export class CanvasMaskPixels {
|
|
4
|
+
filter;
|
|
5
|
+
offset;
|
|
4
6
|
constructor() {
|
|
5
7
|
this.filter = (pixel) => pixel.a > minAlpha;
|
|
6
8
|
this.offset = 4;
|
|
@@ -11,7 +13,7 @@ export class CanvasMaskPixels {
|
|
|
11
13
|
}
|
|
12
14
|
if (data.filter !== undefined) {
|
|
13
15
|
if (isString(data.filter)) {
|
|
14
|
-
if (
|
|
16
|
+
if (data.filter in globalThis) {
|
|
15
17
|
const filter = globalThis[data.filter];
|
|
16
18
|
if (isFunction(filter)) {
|
|
17
19
|
this.filter = filter;
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { isNull } from "@tsparticles/engine";
|
|
2
2
|
export class FontTextMask {
|
|
3
|
+
family;
|
|
4
|
+
size;
|
|
5
|
+
style;
|
|
6
|
+
variant;
|
|
7
|
+
weight;
|
|
3
8
|
constructor() {
|
|
4
9
|
this.family = "sans-serif";
|
|
5
10
|
this.size = 100;
|
|
11
|
+
this.style = "";
|
|
12
|
+
this.variant = "";
|
|
13
|
+
this.weight = "";
|
|
6
14
|
}
|
|
7
15
|
load(data) {
|
|
8
16
|
if (isNull(data)) {
|
|
@@ -2,8 +2,14 @@ import { isNull } from "@tsparticles/engine";
|
|
|
2
2
|
import { FontTextMask } from "./FontTextMask.js";
|
|
3
3
|
import { TextMaskLine } from "./TextMaskLine.js";
|
|
4
4
|
export class TextMask {
|
|
5
|
+
color;
|
|
6
|
+
fill;
|
|
7
|
+
font;
|
|
8
|
+
lines;
|
|
9
|
+
text;
|
|
5
10
|
constructor() {
|
|
6
11
|
this.color = "#000000";
|
|
12
|
+
this.fill = true;
|
|
7
13
|
this.font = new FontTextMask();
|
|
8
14
|
this.lines = new TextMaskLine();
|
|
9
15
|
this.text = "";
|
|
@@ -15,6 +21,9 @@ export class TextMask {
|
|
|
15
21
|
if (data.color !== undefined) {
|
|
16
22
|
this.color = data.color;
|
|
17
23
|
}
|
|
24
|
+
if (data.fill !== undefined) {
|
|
25
|
+
this.fill = data.fill;
|
|
26
|
+
}
|
|
18
27
|
this.font.load(data.font);
|
|
19
28
|
this.lines.load(data.lines);
|
|
20
29
|
if (data.text !== undefined) {
|
package/browser/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export async function loadCanvasMaskPlugin(engine) {
|
|
2
|
-
engine.checkVersion("4.0.0-
|
|
2
|
+
engine.checkVersion("4.0.0-beta.0");
|
|
3
3
|
await engine.register(async (e) => {
|
|
4
4
|
const { CanvasMaskPlugin } = await import("./CanvasMaskPlugin.js");
|
|
5
5
|
e.addPlugin(new CanvasMaskPlugin());
|
package/browser/utils.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const defaultWidth = 0, defaultRgb = 0;
|
|
1
|
+
import { getRandom, half, percentDenominator, } from "@tsparticles/engine";
|
|
3
2
|
export function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
|
|
4
3
|
const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
|
|
5
4
|
let selectedPixels = 0;
|
|
@@ -28,8 +27,11 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
|
|
|
28
27
|
y: pixelPos.y * scale + positionOffset.y,
|
|
29
28
|
}, pOptions = {};
|
|
30
29
|
if (override.color) {
|
|
31
|
-
pOptions.
|
|
32
|
-
|
|
30
|
+
pOptions.fill = {
|
|
31
|
+
color: {
|
|
32
|
+
value: pixel,
|
|
33
|
+
},
|
|
34
|
+
enable: true,
|
|
33
35
|
};
|
|
34
36
|
}
|
|
35
37
|
if (override.opacity) {
|
|
@@ -41,91 +43,6 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
|
|
|
41
43
|
selectedPixels++;
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
45
|
-
const imageData = ctx.getImageData(originPoint.x, originPoint.y, size.width, size.height).data;
|
|
46
|
-
if (clear) {
|
|
47
|
-
ctx.clearRect(originPoint.x, originPoint.y, size.width, size.height);
|
|
48
|
-
}
|
|
49
|
-
const pixels = [];
|
|
50
|
-
for (let i = 0; i < imageData.length; i += offset) {
|
|
51
|
-
const idx = i / offset, pos = {
|
|
52
|
-
x: idx % size.width,
|
|
53
|
-
y: Math.floor(idx / size.width),
|
|
54
|
-
};
|
|
55
|
-
pixels[pos.y] ??= [];
|
|
56
|
-
const indexesOffset = {
|
|
57
|
-
r: 0,
|
|
58
|
-
g: 1,
|
|
59
|
-
b: 2,
|
|
60
|
-
a: 3,
|
|
61
|
-
}, alphaFactor = 255, row = pixels[pos.y];
|
|
62
|
-
if (!row) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
row[pos.x] = {
|
|
66
|
-
r: imageData[i + indexesOffset.r] ?? defaultRgb,
|
|
67
|
-
g: imageData[i + indexesOffset.g] ?? defaultRgb,
|
|
68
|
-
b: imageData[i + indexesOffset.b] ?? defaultRgb,
|
|
69
|
-
a: (imageData[i + indexesOffset.a] ?? defaultAlpha) / alphaFactor,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
pixels,
|
|
74
|
-
width: Math.min(...pixels.map(row => row.length)),
|
|
75
|
-
height: pixels.length,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
export function getImageData(src, offset) {
|
|
79
|
-
const image = new Image();
|
|
80
|
-
image.crossOrigin = "Anonymous";
|
|
81
|
-
const p = new Promise((resolve, reject) => {
|
|
82
|
-
image.onerror = reject;
|
|
83
|
-
image.onload = () => {
|
|
84
|
-
const canvas = safeDocument().createElement("canvas");
|
|
85
|
-
canvas.width = image.width;
|
|
86
|
-
canvas.height = image.height;
|
|
87
|
-
const context = canvas.getContext("2d");
|
|
88
|
-
if (!context) {
|
|
89
|
-
reject(new Error("Could not get canvas context"));
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
context.drawImage(image, originPoint.x, originPoint.y, image.width, image.height, originPoint.x, originPoint.y, canvas.width, canvas.height);
|
|
93
|
-
resolve(getCanvasImageData(context, canvas, offset));
|
|
94
|
-
};
|
|
95
|
-
});
|
|
96
|
-
image.src = src;
|
|
97
|
-
return p;
|
|
98
|
-
}
|
|
99
|
-
export function getTextData(textOptions, offset) {
|
|
100
|
-
const canvas = safeDocument().createElement("canvas"), context = canvas.getContext("2d"), { font, text, lines: linesOptions, color } = textOptions;
|
|
101
|
-
if (!text || !context) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const lines = text.split(linesOptions.separator), fontSize = isNumber(font.size) ? `${font.size.toString()}px` : font.size, linesData = [];
|
|
105
|
-
let maxWidth = 0, totalHeight = 0;
|
|
106
|
-
for (const line of lines) {
|
|
107
|
-
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight?.toString() ?? ""} ${fontSize} ${font.family}`;
|
|
108
|
-
const measure = context.measureText(line), lineData = {
|
|
109
|
-
measure,
|
|
110
|
-
text: line,
|
|
111
|
-
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
112
|
-
width: measure.width,
|
|
113
|
-
};
|
|
114
|
-
maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
|
|
115
|
-
totalHeight += lineData.height + linesOptions.spacing;
|
|
116
|
-
linesData.push(lineData);
|
|
117
|
-
}
|
|
118
|
-
canvas.width = maxWidth;
|
|
119
|
-
canvas.height = totalHeight;
|
|
120
|
-
let currentHeight = 0;
|
|
121
|
-
for (const line of linesData) {
|
|
122
|
-
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight?.toString() ?? ""} ${fontSize} ${font.family}`;
|
|
123
|
-
context.fillStyle = color;
|
|
124
|
-
context.fillText(line.text, originPoint.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
125
|
-
currentHeight += line.height + linesOptions.spacing;
|
|
126
|
-
}
|
|
127
|
-
return getCanvasImageData(context, canvas, offset);
|
|
128
|
-
}
|
|
129
46
|
function shuffle(array) {
|
|
130
47
|
const lengthOffset = 1, minIndex = 0;
|
|
131
48
|
for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
|
package/cjs/CanvasMaskPlugin.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { CanvasMask } from "./Options/Classes/CanvasMask.js";
|
|
2
2
|
export class CanvasMaskPlugin {
|
|
3
|
-
|
|
4
|
-
this.id = "canvasMask";
|
|
5
|
-
}
|
|
3
|
+
id = "canvas-mask";
|
|
6
4
|
async getPlugin(container) {
|
|
7
5
|
const { CanvasMaskPluginInstance } = await import("./CanvasMaskPluginInstance.js");
|
|
8
6
|
return new CanvasMaskPluginInstance(container);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getCanvasImageData, getImageData, getTextData } from "@tsparticles/canvas-utils";
|
|
2
2
|
import { isNull, safeDocument } from "@tsparticles/engine";
|
|
3
|
+
import { addParticlesFromCanvasPixels } from "./utils.js";
|
|
3
4
|
export class CanvasMaskPluginInstance {
|
|
5
|
+
_container;
|
|
4
6
|
constructor(container) {
|
|
5
7
|
this._container = container;
|
|
6
8
|
}
|
|
@@ -20,23 +22,21 @@ export class CanvasMaskPluginInstance {
|
|
|
20
22
|
if (!url) {
|
|
21
23
|
return;
|
|
22
24
|
}
|
|
23
|
-
pixelData = await getImageData(url, offset);
|
|
25
|
+
pixelData = await getImageData(url, offset, container.canvas.settings);
|
|
24
26
|
}
|
|
25
27
|
else if (options.text) {
|
|
26
|
-
const textOptions = options.text;
|
|
27
|
-
const data = getTextData(textOptions, offset);
|
|
28
|
+
const textOptions = options.text, data = getTextData(textOptions, offset, textOptions.fill, container.canvas.settings);
|
|
28
29
|
if (isNull(data)) {
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
32
|
pixelData = data;
|
|
32
33
|
}
|
|
33
34
|
else if (options.element ?? options.selector) {
|
|
34
|
-
const canvas = options.element ??
|
|
35
|
-
(options.selector && safeDocument().querySelector(options.selector));
|
|
35
|
+
const canvas = options.element ?? (options.selector && safeDocument().querySelector(options.selector));
|
|
36
36
|
if (!canvas) {
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
const context = canvas.getContext("2d");
|
|
39
|
+
const context = canvas.getContext("2d", container.canvas.settings);
|
|
40
40
|
if (!context) {
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
@@ -4,6 +4,15 @@ import { CanvasMaskPixels } from "./CanvasMaskPixels.js";
|
|
|
4
4
|
import { ImageMask } from "./ImageMask.js";
|
|
5
5
|
import { TextMask } from "./TextMask.js";
|
|
6
6
|
export class CanvasMask {
|
|
7
|
+
element;
|
|
8
|
+
enable;
|
|
9
|
+
image;
|
|
10
|
+
override;
|
|
11
|
+
pixels;
|
|
12
|
+
position;
|
|
13
|
+
scale;
|
|
14
|
+
selector;
|
|
15
|
+
text;
|
|
7
16
|
constructor() {
|
|
8
17
|
this.enable = false;
|
|
9
18
|
this.override = new CanvasMaskOverride();
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { isFunction, isNull, isString, } from "@tsparticles/engine";
|
|
2
2
|
const minAlpha = 0;
|
|
3
3
|
export class CanvasMaskPixels {
|
|
4
|
+
filter;
|
|
5
|
+
offset;
|
|
4
6
|
constructor() {
|
|
5
7
|
this.filter = (pixel) => pixel.a > minAlpha;
|
|
6
8
|
this.offset = 4;
|
|
@@ -11,7 +13,7 @@ export class CanvasMaskPixels {
|
|
|
11
13
|
}
|
|
12
14
|
if (data.filter !== undefined) {
|
|
13
15
|
if (isString(data.filter)) {
|
|
14
|
-
if (
|
|
16
|
+
if (data.filter in globalThis) {
|
|
15
17
|
const filter = globalThis[data.filter];
|
|
16
18
|
if (isFunction(filter)) {
|
|
17
19
|
this.filter = filter;
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { isNull } from "@tsparticles/engine";
|
|
2
2
|
export class FontTextMask {
|
|
3
|
+
family;
|
|
4
|
+
size;
|
|
5
|
+
style;
|
|
6
|
+
variant;
|
|
7
|
+
weight;
|
|
3
8
|
constructor() {
|
|
4
9
|
this.family = "sans-serif";
|
|
5
10
|
this.size = 100;
|
|
11
|
+
this.style = "";
|
|
12
|
+
this.variant = "";
|
|
13
|
+
this.weight = "";
|
|
6
14
|
}
|
|
7
15
|
load(data) {
|
|
8
16
|
if (isNull(data)) {
|
|
@@ -2,8 +2,14 @@ import { isNull } from "@tsparticles/engine";
|
|
|
2
2
|
import { FontTextMask } from "./FontTextMask.js";
|
|
3
3
|
import { TextMaskLine } from "./TextMaskLine.js";
|
|
4
4
|
export class TextMask {
|
|
5
|
+
color;
|
|
6
|
+
fill;
|
|
7
|
+
font;
|
|
8
|
+
lines;
|
|
9
|
+
text;
|
|
5
10
|
constructor() {
|
|
6
11
|
this.color = "#000000";
|
|
12
|
+
this.fill = true;
|
|
7
13
|
this.font = new FontTextMask();
|
|
8
14
|
this.lines = new TextMaskLine();
|
|
9
15
|
this.text = "";
|
|
@@ -15,6 +21,9 @@ export class TextMask {
|
|
|
15
21
|
if (data.color !== undefined) {
|
|
16
22
|
this.color = data.color;
|
|
17
23
|
}
|
|
24
|
+
if (data.fill !== undefined) {
|
|
25
|
+
this.fill = data.fill;
|
|
26
|
+
}
|
|
18
27
|
this.font.load(data.font);
|
|
19
28
|
this.lines.load(data.lines);
|
|
20
29
|
if (data.text !== undefined) {
|
package/cjs/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export async function loadCanvasMaskPlugin(engine) {
|
|
2
|
-
engine.checkVersion("4.0.0-
|
|
2
|
+
engine.checkVersion("4.0.0-beta.0");
|
|
3
3
|
await engine.register(async (e) => {
|
|
4
4
|
const { CanvasMaskPlugin } = await import("./CanvasMaskPlugin.js");
|
|
5
5
|
e.addPlugin(new CanvasMaskPlugin());
|
package/cjs/utils.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
const defaultWidth = 0, defaultRgb = 0;
|
|
1
|
+
import { getRandom, half, percentDenominator, } from "@tsparticles/engine";
|
|
3
2
|
export function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
|
|
4
3
|
const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
|
|
5
4
|
let selectedPixels = 0;
|
|
@@ -28,8 +27,11 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
|
|
|
28
27
|
y: pixelPos.y * scale + positionOffset.y,
|
|
29
28
|
}, pOptions = {};
|
|
30
29
|
if (override.color) {
|
|
31
|
-
pOptions.
|
|
32
|
-
|
|
30
|
+
pOptions.fill = {
|
|
31
|
+
color: {
|
|
32
|
+
value: pixel,
|
|
33
|
+
},
|
|
34
|
+
enable: true,
|
|
33
35
|
};
|
|
34
36
|
}
|
|
35
37
|
if (override.opacity) {
|
|
@@ -41,91 +43,6 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
|
|
|
41
43
|
selectedPixels++;
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
45
|
-
const imageData = ctx.getImageData(originPoint.x, originPoint.y, size.width, size.height).data;
|
|
46
|
-
if (clear) {
|
|
47
|
-
ctx.clearRect(originPoint.x, originPoint.y, size.width, size.height);
|
|
48
|
-
}
|
|
49
|
-
const pixels = [];
|
|
50
|
-
for (let i = 0; i < imageData.length; i += offset) {
|
|
51
|
-
const idx = i / offset, pos = {
|
|
52
|
-
x: idx % size.width,
|
|
53
|
-
y: Math.floor(idx / size.width),
|
|
54
|
-
};
|
|
55
|
-
pixels[pos.y] ??= [];
|
|
56
|
-
const indexesOffset = {
|
|
57
|
-
r: 0,
|
|
58
|
-
g: 1,
|
|
59
|
-
b: 2,
|
|
60
|
-
a: 3,
|
|
61
|
-
}, alphaFactor = 255, row = pixels[pos.y];
|
|
62
|
-
if (!row) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
row[pos.x] = {
|
|
66
|
-
r: imageData[i + indexesOffset.r] ?? defaultRgb,
|
|
67
|
-
g: imageData[i + indexesOffset.g] ?? defaultRgb,
|
|
68
|
-
b: imageData[i + indexesOffset.b] ?? defaultRgb,
|
|
69
|
-
a: (imageData[i + indexesOffset.a] ?? defaultAlpha) / alphaFactor,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
pixels,
|
|
74
|
-
width: Math.min(...pixels.map(row => row.length)),
|
|
75
|
-
height: pixels.length,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
export function getImageData(src, offset) {
|
|
79
|
-
const image = new Image();
|
|
80
|
-
image.crossOrigin = "Anonymous";
|
|
81
|
-
const p = new Promise((resolve, reject) => {
|
|
82
|
-
image.onerror = reject;
|
|
83
|
-
image.onload = () => {
|
|
84
|
-
const canvas = safeDocument().createElement("canvas");
|
|
85
|
-
canvas.width = image.width;
|
|
86
|
-
canvas.height = image.height;
|
|
87
|
-
const context = canvas.getContext("2d");
|
|
88
|
-
if (!context) {
|
|
89
|
-
reject(new Error("Could not get canvas context"));
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
context.drawImage(image, originPoint.x, originPoint.y, image.width, image.height, originPoint.x, originPoint.y, canvas.width, canvas.height);
|
|
93
|
-
resolve(getCanvasImageData(context, canvas, offset));
|
|
94
|
-
};
|
|
95
|
-
});
|
|
96
|
-
image.src = src;
|
|
97
|
-
return p;
|
|
98
|
-
}
|
|
99
|
-
export function getTextData(textOptions, offset) {
|
|
100
|
-
const canvas = safeDocument().createElement("canvas"), context = canvas.getContext("2d"), { font, text, lines: linesOptions, color } = textOptions;
|
|
101
|
-
if (!text || !context) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const lines = text.split(linesOptions.separator), fontSize = isNumber(font.size) ? `${font.size.toString()}px` : font.size, linesData = [];
|
|
105
|
-
let maxWidth = 0, totalHeight = 0;
|
|
106
|
-
for (const line of lines) {
|
|
107
|
-
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight?.toString() ?? ""} ${fontSize} ${font.family}`;
|
|
108
|
-
const measure = context.measureText(line), lineData = {
|
|
109
|
-
measure,
|
|
110
|
-
text: line,
|
|
111
|
-
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
112
|
-
width: measure.width,
|
|
113
|
-
};
|
|
114
|
-
maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
|
|
115
|
-
totalHeight += lineData.height + linesOptions.spacing;
|
|
116
|
-
linesData.push(lineData);
|
|
117
|
-
}
|
|
118
|
-
canvas.width = maxWidth;
|
|
119
|
-
canvas.height = totalHeight;
|
|
120
|
-
let currentHeight = 0;
|
|
121
|
-
for (const line of linesData) {
|
|
122
|
-
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight?.toString() ?? ""} ${fontSize} ${font.family}`;
|
|
123
|
-
context.fillStyle = color;
|
|
124
|
-
context.fillText(line.text, originPoint.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
125
|
-
currentHeight += line.height + linesOptions.spacing;
|
|
126
|
-
}
|
|
127
|
-
return getCanvasImageData(context, canvas, offset);
|
|
128
|
-
}
|
|
129
46
|
function shuffle(array) {
|
|
130
47
|
const lengthOffset = 1, minIndex = 0;
|
|
131
48
|
for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
|
|
@@ -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
|
-
* v4.0.0-
|
|
7
|
+
* v4.0.0-beta.0
|
|
8
8
|
*/
|
|
9
9
|
"use strict";
|
|
10
10
|
/*
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
\**************************************************/
|
|
24
24
|
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
25
25
|
|
|
26
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CanvasMaskPluginInstance: () => (/* binding */ CanvasMaskPluginInstance)\n/* harmony export */ });\n/* harmony import */ var
|
|
26
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CanvasMaskPluginInstance: () => (/* binding */ CanvasMaskPluginInstance)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_canvas_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/canvas-utils */ \"@tsparticles/canvas-utils\");\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils.js */ \"./dist/browser/utils.js\");\n\n\n\nclass CanvasMaskPluginInstance {\n _container;\n constructor(container){\n this._container = container;\n }\n async init() {\n const container = this._container, 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,_tsparticles_canvas_utils__WEBPACK_IMPORTED_MODULE_0__.getImageData)(url, offset, container.canvas.settings);\n } else if (options.text) {\n const textOptions = options.text, data = (0,_tsparticles_canvas_utils__WEBPACK_IMPORTED_MODULE_0__.getTextData)(textOptions, offset, textOptions.fill, container.canvas.settings);\n if ((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__.isNull)(data)) {\n return;\n }\n pixelData = data;\n } else if (options.element ?? options.selector) {\n const canvas = options.element ?? (options.selector && (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__.safeDocument)().querySelector(options.selector));\n if (!canvas) {\n return;\n }\n const context = canvas.getContext(\"2d\", container.canvas.settings);\n if (!context) {\n return;\n }\n pixelData = (0,_tsparticles_canvas_utils__WEBPACK_IMPORTED_MODULE_0__.getCanvasImageData)(context, canvas, offset);\n }\n (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.addParticlesFromCanvasPixels)(container, pixelData, options.position, options.scale, options.override, options.pixels.filter);\n }\n}\n\n\n//# sourceURL=webpack://@tsparticles/plugin-canvas-mask/./dist/browser/CanvasMaskPluginInstance.js?\n}");
|
|
27
27
|
|
|
28
28
|
/***/ },
|
|
29
29
|
|
|
@@ -33,7 +33,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
|
|
|
33
33
|
\*******************************/
|
|
34
34
|
(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
|
|
35
35
|
|
|
36
|
-
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addParticlesFromCanvasPixels: () => (/* binding */ addParticlesFromCanvasPixels)
|
|
36
|
+
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ addParticlesFromCanvasPixels: () => (/* binding */ addParticlesFromCanvasPixels)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n\nfunction addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {\n const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), 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 * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half,\n y: canvasSize.height * position.y / _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.percentDenominator - height * scale * _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.half\n };\n while(selectedPixels < maxParticles && indexArray.length){\n const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {\n x: nextIndex % width,\n y: Math.floor(nextIndex / width)\n }, row = data.pixels[pixelPos.y];\n if (!row) {\n continue;\n }\n const pixel = row[pixelPos.x];\n if (!pixel) {\n continue;\n }\n const 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 }, pOptions = {};\n if (override.color) {\n pOptions.fill = {\n color: {\n value: pixel\n },\n enable: true\n };\n }\n if (override.opacity) {\n pOptions.opacity = {\n value: pixel.a\n };\n }\n container.particles.addParticle(pos, pOptions);\n selectedPixels++;\n }\n}\nfunction shuffle(array) {\n const lengthOffset = 1, 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), currentItem = array[currentIndex], randomItem = array[randomIndex];\n if (randomItem === currentItem) {\n continue;\n }\n if (randomItem === undefined || currentItem === undefined) {\n continue;\n }\n array[currentIndex] = randomItem;\n array[randomIndex] = currentItem;\n }\n return array;\n}\nconst range = (n)=>[\n ...Array(n).keys()\n ];\n\n\n//# sourceURL=webpack://@tsparticles/plugin-canvas-mask/./dist/browser/utils.js?\n}");
|
|
37
37
|
|
|
38
38
|
/***/ }
|
|
39
39
|
|