@tsparticles/plugin-canvas-mask 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser/CanvasMaskInstance.js +4 -5
- package/browser/Options/Classes/CanvasMaskPixels.js +2 -1
- package/browser/index.js +3 -4
- package/browser/utils.js +27 -16
- package/cjs/CanvasMaskInstance.js +3 -4
- package/cjs/Options/Classes/CanvasMaskPixels.js +2 -1
- package/cjs/index.js +3 -4
- package/cjs/utils.js +26 -15
- package/esm/CanvasMaskInstance.js +4 -5
- package/esm/Options/Classes/CanvasMaskPixels.js +2 -1
- package/esm/index.js +3 -4
- package/esm/utils.js +27 -16
- package/package.json +2 -2
- package/report.html +2 -2
- package/tsparticles.plugin.canvas-mask.js +40 -25
- package/tsparticles.plugin.canvas-mask.min.js +1 -1
- package/tsparticles.plugin.canvas-mask.min.js.LICENSE.txt +1 -1
- package/types/CanvasMaskInstance.d.ts +2 -3
- package/types/Options/Classes/CanvasMaskPixels.d.ts +1 -1
- package/types/utils.d.ts +2 -2
- package/umd/CanvasMaskInstance.js +3 -4
- package/umd/Options/Classes/CanvasMaskPixels.js +2 -1
- package/umd/index.js +3 -4
- package/umd/utils.js +26 -15
|
@@ -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
|
|
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
|
|
34
|
-
const canvas = options.element
|
|
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
|
}
|
package/browser/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { CanvasMask } from "./Options/Classes/CanvasMask.js";
|
|
2
2
|
import { CanvasMaskInstance } from "./CanvasMaskInstance.js";
|
|
3
3
|
class CanvasMaskPlugin {
|
|
4
|
-
constructor(
|
|
4
|
+
constructor() {
|
|
5
5
|
this.id = "canvasMask";
|
|
6
|
-
this._engine = engine;
|
|
7
6
|
}
|
|
8
7
|
getPlugin(container) {
|
|
9
|
-
return new CanvasMaskInstance(container
|
|
8
|
+
return new CanvasMaskInstance(container);
|
|
10
9
|
}
|
|
11
10
|
loadOptions(options, source) {
|
|
12
11
|
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
@@ -23,5 +22,5 @@ class CanvasMaskPlugin {
|
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
export async function loadCanvasMaskPlugin(engine, refresh = true) {
|
|
26
|
-
await engine.addPlugin(new CanvasMaskPlugin(
|
|
25
|
+
await engine.addPlugin(new CanvasMaskPlugin(), refresh);
|
|
27
26
|
}
|
package/browser/utils.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { errorPrefix, getRandom, isNumber, } from "@tsparticles/engine";
|
|
1
|
+
import { errorPrefix, getRandom, isNumber, percentDenominator, } from "@tsparticles/engine";
|
|
2
|
+
const half = 0.5, origin = {
|
|
3
|
+
x: 0,
|
|
4
|
+
y: 0,
|
|
5
|
+
}, defaultWidth = 0;
|
|
2
6
|
export function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
|
|
3
7
|
const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
|
|
4
8
|
let selectedPixels = 0;
|
|
5
9
|
const positionOffset = {
|
|
6
|
-
x: (canvasSize.width * position.x) /
|
|
7
|
-
y: (canvasSize.height * position.y) /
|
|
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()
|
|
14
|
+
const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
|
|
11
15
|
x: nextIndex % width,
|
|
12
16
|
y: Math.floor(nextIndex / width),
|
|
13
17
|
}, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
|
|
@@ -33,9 +37,9 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
|
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
36
|
-
const imageData = ctx.getImageData(
|
|
40
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
37
41
|
if (clear) {
|
|
38
|
-
ctx.clearRect(
|
|
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 +
|
|
52
|
-
b: imageData[i +
|
|
53
|
-
a: imageData[i +
|
|
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,
|
|
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
|
|
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 ||
|
|
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
|
|
115
|
+
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
|
|
106
116
|
context.fillStyle = color;
|
|
107
|
-
context.fillText(line.text,
|
|
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
|
-
|
|
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
|
|
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
|
|
37
|
-
const canvas = options.element
|
|
35
|
+
else if (options.element ?? options.selector) {
|
|
36
|
+
const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
|
|
38
37
|
if (!canvas) {
|
|
39
38
|
return;
|
|
40
39
|
}
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CanvasMaskPixels = void 0;
|
|
4
4
|
const engine_1 = require("@tsparticles/engine");
|
|
5
|
+
const minAlpha = 0;
|
|
5
6
|
class CanvasMaskPixels {
|
|
6
7
|
constructor() {
|
|
7
|
-
this.filter = (pixel) => pixel.a >
|
|
8
|
+
this.filter = (pixel) => pixel.a > minAlpha;
|
|
8
9
|
this.offset = 4;
|
|
9
10
|
}
|
|
10
11
|
load(data) {
|
package/cjs/index.js
CHANGED
|
@@ -4,12 +4,11 @@ exports.loadCanvasMaskPlugin = void 0;
|
|
|
4
4
|
const CanvasMask_js_1 = require("./Options/Classes/CanvasMask.js");
|
|
5
5
|
const CanvasMaskInstance_js_1 = require("./CanvasMaskInstance.js");
|
|
6
6
|
class CanvasMaskPlugin {
|
|
7
|
-
constructor(
|
|
7
|
+
constructor() {
|
|
8
8
|
this.id = "canvasMask";
|
|
9
|
-
this._engine = engine;
|
|
10
9
|
}
|
|
11
10
|
getPlugin(container) {
|
|
12
|
-
return new CanvasMaskInstance_js_1.CanvasMaskInstance(container
|
|
11
|
+
return new CanvasMaskInstance_js_1.CanvasMaskInstance(container);
|
|
13
12
|
}
|
|
14
13
|
loadOptions(options, source) {
|
|
15
14
|
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
@@ -26,6 +25,6 @@ class CanvasMaskPlugin {
|
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
async function loadCanvasMaskPlugin(engine, refresh = true) {
|
|
29
|
-
await engine.addPlugin(new CanvasMaskPlugin(
|
|
28
|
+
await engine.addPlugin(new CanvasMaskPlugin(), refresh);
|
|
30
29
|
}
|
|
31
30
|
exports.loadCanvasMaskPlugin = loadCanvasMaskPlugin;
|
package/cjs/utils.js
CHANGED
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getTextData = exports.getImageData = exports.getCanvasImageData = exports.addParticlesFromCanvasPixels = void 0;
|
|
4
4
|
const engine_1 = require("@tsparticles/engine");
|
|
5
|
+
const half = 0.5, origin = {
|
|
6
|
+
x: 0,
|
|
7
|
+
y: 0,
|
|
8
|
+
}, defaultWidth = 0;
|
|
5
9
|
function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
|
|
6
10
|
const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
|
|
7
11
|
let selectedPixels = 0;
|
|
8
12
|
const positionOffset = {
|
|
9
|
-
x: (canvasSize.width * position.x) /
|
|
10
|
-
y: (canvasSize.height * position.y) /
|
|
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()
|
|
17
|
+
const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
|
|
14
18
|
x: nextIndex % width,
|
|
15
19
|
y: Math.floor(nextIndex / width),
|
|
16
20
|
}, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
|
|
@@ -37,9 +41,9 @@ function addParticlesFromCanvasPixels(container, data, position, scale, override
|
|
|
37
41
|
}
|
|
38
42
|
exports.addParticlesFromCanvasPixels = addParticlesFromCanvasPixels;
|
|
39
43
|
function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
40
|
-
const imageData = ctx.getImageData(
|
|
44
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
41
45
|
if (clear) {
|
|
42
|
-
ctx.clearRect(
|
|
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 +
|
|
56
|
-
b: imageData[i +
|
|
57
|
-
a: imageData[i +
|
|
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,
|
|
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
|
|
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 ||
|
|
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
|
|
121
|
+
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
|
|
112
122
|
context.fillStyle = color;
|
|
113
|
-
context.fillText(line.text,
|
|
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
|
-
|
|
130
|
+
const lengthOffset = 1, minIndex = 0;
|
|
131
|
+
for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
|
|
121
132
|
const randomIndex = Math.floor((0, engine_1.getRandom)() * currentIndex);
|
|
122
133
|
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
|
|
123
134
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { addParticlesFromCanvasPixels, getCanvasImageData, getImageData, getTextData } from "./utils.js";
|
|
1
|
+
import { addParticlesFromCanvasPixels, getCanvasImageData, getImageData, getTextData, } from "./utils.js";
|
|
2
2
|
export class CanvasMaskInstance {
|
|
3
|
-
constructor(container
|
|
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
|
|
34
|
-
const canvas = options.element
|
|
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
|
}
|
package/esm/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { CanvasMask } from "./Options/Classes/CanvasMask.js";
|
|
2
2
|
import { CanvasMaskInstance } from "./CanvasMaskInstance.js";
|
|
3
3
|
class CanvasMaskPlugin {
|
|
4
|
-
constructor(
|
|
4
|
+
constructor() {
|
|
5
5
|
this.id = "canvasMask";
|
|
6
|
-
this._engine = engine;
|
|
7
6
|
}
|
|
8
7
|
getPlugin(container) {
|
|
9
|
-
return new CanvasMaskInstance(container
|
|
8
|
+
return new CanvasMaskInstance(container);
|
|
10
9
|
}
|
|
11
10
|
loadOptions(options, source) {
|
|
12
11
|
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
@@ -23,5 +22,5 @@ class CanvasMaskPlugin {
|
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
export async function loadCanvasMaskPlugin(engine, refresh = true) {
|
|
26
|
-
await engine.addPlugin(new CanvasMaskPlugin(
|
|
25
|
+
await engine.addPlugin(new CanvasMaskPlugin(), refresh);
|
|
27
26
|
}
|
package/esm/utils.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { errorPrefix, getRandom, isNumber, } from "@tsparticles/engine";
|
|
1
|
+
import { errorPrefix, getRandom, isNumber, percentDenominator, } from "@tsparticles/engine";
|
|
2
|
+
const half = 0.5, origin = {
|
|
3
|
+
x: 0,
|
|
4
|
+
y: 0,
|
|
5
|
+
}, defaultWidth = 0;
|
|
2
6
|
export function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
|
|
3
7
|
const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
|
|
4
8
|
let selectedPixels = 0;
|
|
5
9
|
const positionOffset = {
|
|
6
|
-
x: (canvasSize.width * position.x) /
|
|
7
|
-
y: (canvasSize.height * position.y) /
|
|
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()
|
|
14
|
+
const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
|
|
11
15
|
x: nextIndex % width,
|
|
12
16
|
y: Math.floor(nextIndex / width),
|
|
13
17
|
}, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
|
|
@@ -33,9 +37,9 @@ export function addParticlesFromCanvasPixels(container, data, position, scale, o
|
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
36
|
-
const imageData = ctx.getImageData(
|
|
40
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
37
41
|
if (clear) {
|
|
38
|
-
ctx.clearRect(
|
|
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 +
|
|
52
|
-
b: imageData[i +
|
|
53
|
-
a: imageData[i +
|
|
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,
|
|
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
|
|
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 ||
|
|
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
|
|
115
|
+
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
|
|
106
116
|
context.fillStyle = color;
|
|
107
|
-
context.fillText(line.text,
|
|
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
|
-
|
|
123
|
+
const lengthOffset = 1, minIndex = 0;
|
|
124
|
+
for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
|
|
114
125
|
const randomIndex = Math.floor(getRandom() * currentIndex);
|
|
115
126
|
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
|
|
116
127
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsparticles/plugin-canvas-mask",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "tsParticles canvas mask plugin",
|
|
5
5
|
"homepage": "https://particles.js.org",
|
|
6
6
|
"repository": {
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"./package.json": "./package.json"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@tsparticles/engine": "^3.0
|
|
89
|
+
"@tsparticles/engine": "^3.1.0"
|
|
90
90
|
},
|
|
91
91
|
"publishConfig": {
|
|
92
92
|
"access": "public"
|
package/report.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8"/>
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
6
|
-
<title>@tsparticles/plugin-canvas-mask [
|
|
6
|
+
<title>@tsparticles/plugin-canvas-mask [13 Jan 2024 at 23:02]</title>
|
|
7
7
|
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" />
|
|
8
8
|
|
|
9
9
|
<script>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
<body>
|
|
32
32
|
<div id="app"></div>
|
|
33
33
|
<script>
|
|
34
|
-
window.chartData = [{"label":"tsparticles.plugin.canvas-mask.js","isAsset":true,"statSize":
|
|
34
|
+
window.chartData = [{"label":"tsparticles.plugin.canvas-mask.js","isAsset":true,"statSize":11137,"parsedSize":14991,"gzipSize":3996,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":11095,"groups":[{"id":763,"label":"index.js + 9 modules (concatenated)","path":"./dist/browser/index.js + 9 modules (concatenated)","statSize":11095,"parsedSize":14991,"gzipSize":3996,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser","statSize":11095,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/index.js","statSize":823,"parsedSize":1111,"gzipSize":296,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskInstance.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/CanvasMaskInstance.js","statSize":1327,"parsedSize":1792,"gzipSize":477,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes","statSize":3895,"groups":[{"id":null,"label":"CanvasMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMask.js","statSize":1346,"parsedSize":1818,"gzipSize":484,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskOverride.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMaskOverride.js","statSize":314,"parsedSize":424,"gzipSize":113,"inaccurateSizes":true},{"id":null,"label":"CanvasMaskPixels.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/CanvasMaskPixels.js","statSize":659,"parsedSize":890,"gzipSize":237,"inaccurateSizes":true},{"id":null,"label":"ImageMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/ImageMask.js","statSize":190,"parsedSize":256,"gzipSize":68,"inaccurateSizes":true},{"id":null,"label":"TextMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/TextMask.js","statSize":531,"parsedSize":717,"gzipSize":191,"inaccurateSizes":true},{"id":null,"label":"FontTextMask.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/FontTextMask.js","statSize":534,"parsedSize":721,"gzipSize":192,"inaccurateSizes":true},{"id":null,"label":"TextMaskLine.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/Options/Classes/TextMaskLine.js","statSize":321,"parsedSize":433,"gzipSize":115,"inaccurateSizes":true}],"parsedSize":5262,"gzipSize":1402,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 9 modules (concatenated)/dist/browser/utils.js","statSize":5050,"parsedSize":6823,"gzipSize":1818,"inaccurateSizes":true}],"parsedSize":14991,"gzipSize":3996,"inaccurateSizes":true}]}],"parsedSize":14991,"gzipSize":3996},{"label":"engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":533,"label":"engine\",\"root\":\"window\"}","path":"./engine\",\"commonjs2\":\"@tsparticles/engine\",\"amd\":\"@tsparticles/engine\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.plugin.canvas-mask":true}}];
|
|
35
35
|
window.entrypoints = ["tsparticles.plugin.canvas-mask","tsparticles.plugin.canvas-mask.min"];
|
|
36
36
|
window.defaultSizes = "parsed";
|
|
37
37
|
</script>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Demo / Generator : https://particles.js.org/
|
|
5
5
|
* GitHub : https://www.github.com/matteobruni/tsparticles
|
|
6
6
|
* How to use? : Check the GitHub README
|
|
7
|
-
* v3.0
|
|
7
|
+
* v3.1.0
|
|
8
8
|
*/
|
|
9
9
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
10
10
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
@@ -116,9 +116,10 @@ class CanvasMaskOverride {
|
|
|
116
116
|
var engine_root_window_ = __webpack_require__(533);
|
|
117
117
|
;// CONCATENATED MODULE: ./dist/browser/Options/Classes/CanvasMaskPixels.js
|
|
118
118
|
|
|
119
|
+
const minAlpha = 0;
|
|
119
120
|
class CanvasMaskPixels {
|
|
120
121
|
constructor() {
|
|
121
|
-
this.filter = pixel => pixel.a >
|
|
122
|
+
this.filter = pixel => pixel.a > minAlpha;
|
|
122
123
|
this.offset = 4;
|
|
123
124
|
}
|
|
124
125
|
load(data) {
|
|
@@ -281,6 +282,12 @@ class CanvasMask {
|
|
|
281
282
|
}
|
|
282
283
|
;// CONCATENATED MODULE: ./dist/browser/utils.js
|
|
283
284
|
|
|
285
|
+
const half = 0.5,
|
|
286
|
+
origin = {
|
|
287
|
+
x: 0,
|
|
288
|
+
y: 0
|
|
289
|
+
},
|
|
290
|
+
defaultWidth = 0;
|
|
284
291
|
function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
|
|
285
292
|
const {
|
|
286
293
|
height,
|
|
@@ -292,11 +299,12 @@ function addParticlesFromCanvasPixels(container, data, position, scale, override
|
|
|
292
299
|
canvasSize = container.canvas.size;
|
|
293
300
|
let selectedPixels = 0;
|
|
294
301
|
const positionOffset = {
|
|
295
|
-
x: canvasSize.width * position.x /
|
|
296
|
-
y: canvasSize.height * position.y /
|
|
302
|
+
x: canvasSize.width * position.x / engine_root_window_.percentDenominator - width * scale * half,
|
|
303
|
+
y: canvasSize.height * position.y / engine_root_window_.percentDenominator - height * scale * half
|
|
297
304
|
};
|
|
298
305
|
while (selectedPixels < maxParticles && indexArray.length) {
|
|
299
|
-
const
|
|
306
|
+
const defaultIndex = 0,
|
|
307
|
+
nextIndex = indexArray.pop() ?? defaultIndex,
|
|
300
308
|
pixelPos = {
|
|
301
309
|
x: nextIndex % width,
|
|
302
310
|
y: Math.floor(nextIndex / width)
|
|
@@ -326,9 +334,9 @@ function addParticlesFromCanvasPixels(container, data, position, scale, override
|
|
|
326
334
|
}
|
|
327
335
|
}
|
|
328
336
|
function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
329
|
-
const imageData = ctx.getImageData(
|
|
337
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
330
338
|
if (clear) {
|
|
331
|
-
ctx.clearRect(
|
|
339
|
+
ctx.clearRect(origin.x, origin.y, size.width, size.height);
|
|
332
340
|
}
|
|
333
341
|
const pixels = [];
|
|
334
342
|
for (let i = 0; i < imageData.length; i += offset) {
|
|
@@ -340,11 +348,18 @@ function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
|
340
348
|
if (!pixels[pos.y]) {
|
|
341
349
|
pixels[pos.y] = [];
|
|
342
350
|
}
|
|
351
|
+
const indexesOffset = {
|
|
352
|
+
r: 0,
|
|
353
|
+
g: 1,
|
|
354
|
+
b: 2,
|
|
355
|
+
a: 3
|
|
356
|
+
},
|
|
357
|
+
alphaFactor = 255;
|
|
343
358
|
pixels[pos.y][pos.x] = {
|
|
344
|
-
r: imageData[i],
|
|
345
|
-
g: imageData[i +
|
|
346
|
-
b: imageData[i +
|
|
347
|
-
a: imageData[i +
|
|
359
|
+
r: imageData[i + indexesOffset.r],
|
|
360
|
+
g: imageData[i + indexesOffset.g],
|
|
361
|
+
b: imageData[i + indexesOffset.b],
|
|
362
|
+
a: imageData[i + indexesOffset.a] / alphaFactor
|
|
348
363
|
};
|
|
349
364
|
}
|
|
350
365
|
return {
|
|
@@ -366,7 +381,7 @@ function getImageData(src, offset) {
|
|
|
366
381
|
if (!context) {
|
|
367
382
|
return reject(new Error(`${engine_root_window_.errorPrefix} Could not get canvas context`));
|
|
368
383
|
}
|
|
369
|
-
context.drawImage(image,
|
|
384
|
+
context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
|
|
370
385
|
resolve(getCanvasImageData(context, canvas, offset));
|
|
371
386
|
};
|
|
372
387
|
});
|
|
@@ -391,7 +406,7 @@ function getTextData(textOptions, offset) {
|
|
|
391
406
|
let maxWidth = 0,
|
|
392
407
|
totalHeight = 0;
|
|
393
408
|
for (const line of lines) {
|
|
394
|
-
context.font = `${font.style
|
|
409
|
+
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
|
|
395
410
|
const measure = context.measureText(line),
|
|
396
411
|
lineData = {
|
|
397
412
|
measure,
|
|
@@ -399,7 +414,7 @@ function getTextData(textOptions, offset) {
|
|
|
399
414
|
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
400
415
|
width: measure.width
|
|
401
416
|
};
|
|
402
|
-
maxWidth = Math.max(maxWidth ||
|
|
417
|
+
maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
|
|
403
418
|
totalHeight += lineData.height + linesOptions.spacing;
|
|
404
419
|
linesData.push(lineData);
|
|
405
420
|
}
|
|
@@ -407,15 +422,17 @@ function getTextData(textOptions, offset) {
|
|
|
407
422
|
canvas.height = totalHeight;
|
|
408
423
|
let currentHeight = 0;
|
|
409
424
|
for (const line of linesData) {
|
|
410
|
-
context.font = `${font.style
|
|
425
|
+
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
|
|
411
426
|
context.fillStyle = color;
|
|
412
|
-
context.fillText(line.text,
|
|
427
|
+
context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
413
428
|
currentHeight += line.height + linesOptions.spacing;
|
|
414
429
|
}
|
|
415
430
|
return getCanvasImageData(context, canvas, offset);
|
|
416
431
|
}
|
|
417
432
|
function shuffle(array) {
|
|
418
|
-
|
|
433
|
+
const lengthOffset = 1,
|
|
434
|
+
minIndex = 0;
|
|
435
|
+
for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
|
|
419
436
|
const randomIndex = Math.floor((0,engine_root_window_.getRandom)() * currentIndex);
|
|
420
437
|
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
|
|
421
438
|
}
|
|
@@ -425,9 +442,8 @@ const range = n => [...Array(n).keys()];
|
|
|
425
442
|
;// CONCATENATED MODULE: ./dist/browser/CanvasMaskInstance.js
|
|
426
443
|
|
|
427
444
|
class CanvasMaskInstance {
|
|
428
|
-
constructor(container
|
|
445
|
+
constructor(container) {
|
|
429
446
|
this._container = container;
|
|
430
|
-
this._engine = engine;
|
|
431
447
|
}
|
|
432
448
|
async init() {
|
|
433
449
|
const container = this._container,
|
|
@@ -454,8 +470,8 @@ class CanvasMaskInstance {
|
|
|
454
470
|
return;
|
|
455
471
|
}
|
|
456
472
|
pixelData = data;
|
|
457
|
-
} else if (options.element
|
|
458
|
-
const canvas = options.element
|
|
473
|
+
} else if (options.element ?? options.selector) {
|
|
474
|
+
const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
|
|
459
475
|
if (!canvas) {
|
|
460
476
|
return;
|
|
461
477
|
}
|
|
@@ -472,12 +488,11 @@ class CanvasMaskInstance {
|
|
|
472
488
|
|
|
473
489
|
|
|
474
490
|
class CanvasMaskPlugin {
|
|
475
|
-
constructor(
|
|
491
|
+
constructor() {
|
|
476
492
|
this.id = "canvasMask";
|
|
477
|
-
this._engine = engine;
|
|
478
493
|
}
|
|
479
494
|
getPlugin(container) {
|
|
480
|
-
return new CanvasMaskInstance(container
|
|
495
|
+
return new CanvasMaskInstance(container);
|
|
481
496
|
}
|
|
482
497
|
loadOptions(options, source) {
|
|
483
498
|
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
@@ -494,7 +509,7 @@ class CanvasMaskPlugin {
|
|
|
494
509
|
}
|
|
495
510
|
}
|
|
496
511
|
async function loadCanvasMaskPlugin(engine, refresh = true) {
|
|
497
|
-
await engine.addPlugin(new CanvasMaskPlugin(
|
|
512
|
+
await engine.addPlugin(new CanvasMaskPlugin(), refresh);
|
|
498
513
|
}
|
|
499
514
|
})();
|
|
500
515
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! For license information please see tsparticles.plugin.canvas-mask.min.js.LICENSE.txt */
|
|
2
|
-
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/engine")):e(t.window);for(var
|
|
2
|
+
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/engine")):e(t.window);for(var o in i)("object"==typeof exports?exports:t)[o]=i[o]}}(this,(t=>(()=>{"use strict";var e={533:e=>{e.exports=t}},i={};function o(t){var s=i[t];if(void 0!==s)return s.exports;var n=i[t]={exports:{}};return e[t](n,n.exports,o),n.exports}o.d=(t,e)=>{for(var i in e)o.o(e,i)&&!o.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),o.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var s={};return(()=>{o.r(s),o.d(s,{loadCanvasMaskPlugin:()=>x});class t{constructor(){this.color=!0,this.opacity=!1}load(t){t&&(void 0!==t.color&&(this.color=t.color),void 0!==t.opacity&&(this.opacity=t.opacity))}}var e=o(533);class i{constructor(){this.filter=t=>t.a>0,this.offset=4}load(t){if(t){if(void 0!==t.filter)if((0,e.isString)(t.filter)){if(Object.hasOwn(window,t.filter)){const i=window[t.filter];(0,e.isFunction)(i)&&(this.filter=i)}}else this.filter=t.filter;void 0!==t.offset&&(this.offset=t.offset)}}}class n{constructor(){this.src=""}load(t){t&&void 0!==t.src&&(this.src=t.src)}}class r{constructor(){this.family="sans-serif",this.size=100}load(t){t&&(void 0!==t.family&&(this.family=t.family),void 0!==t.size&&(this.size=t.size),void 0!==t.style&&(this.style=t.style),void 0!==t.variant&&(this.variant=t.variant),void 0!==t.weight&&(this.weight=t.weight))}}class a{constructor(){this.separator="\n",this.spacing=10}load(t){t&&(void 0!==t.separator&&(this.separator=t.separator),void 0!==t.spacing&&(this.spacing=t.spacing))}}class c{constructor(){this.color="#000000",this.font=new r,this.lines=new a,this.text=""}load(t){t&&(void 0!==t.color&&(this.color=t.color),this.font.load(t.font),this.lines.load(t.lines),void 0!==t.text&&(this.text=t.text))}}class l{constructor(){this.enable=!1,this.override=new t,this.pixels=new i,this.position={x:50,y:50},this.scale=1}load(t){t&&(void 0!==t.element&&t.element instanceof HTMLCanvasElement&&(this.element=t.element),void 0!==t.enable&&(this.enable=t.enable),t.image&&(this.image||(this.image=new n),this.image.load(t.image)),this.pixels.load(t.pixels),t.position&&(this.position={x:t.position.x??this.position.x,y:t.position.y??this.position.y}),this.override.load(t.override),void 0!==t.scale&&(this.scale=t.scale),void 0!==t.selector&&(this.selector=t.selector),t.text&&(this.text||(this.text=new c),this.text.load(t.text)))}}const h={x:0,y:0};function d(t,i,o,s,n,r){const{height:a,width:c}=i,l=a*c,h=function(t){const i=1,o=0;for(let s=t.length-i;s>=o;s--){const i=Math.floor((0,e.getRandom)()*s);[t[s],t[i]]=[t[i],t[s]]}return t}(u(l)),d=Math.min(l,t.actualOptions.particles.number.value),f=t.canvas.size;let p=0;const g=f.width*o.x/e.percentDenominator-c*s*.5,x=f.height*o.y/e.percentDenominator-a*s*.5;for(;p<d&&h.length;){const e=0,o=h.pop()??e,a={x:o%c,y:Math.floor(o/c)},l=i.pixels[a.y][a.x];if(!r(l))continue;const d={x:a.x*s+g,y:a.y*s+x},f={};n.color&&(f.color={value:l}),n.opacity&&(f.opacity={value:l.a}),t.particles.addParticle(d,f),p++}}function f(t,e,i,o=!0){const s=t.getImageData(h.x,h.y,e.width,e.height).data;o&&t.clearRect(h.x,h.y,e.width,e.height);const n=[];for(let t=0;t<s.length;t+=i){const o=t/i,r={x:o%e.width,y:Math.floor(o/e.width)};n[r.y]||(n[r.y]=[]);const a={r:0,g:1,b:2,a:3},c=255;n[r.y][r.x]={r:s[t+a.r],g:s[t+a.g],b:s[t+a.b],a:s[t+a.a]/c}}return{pixels:n,width:Math.min(...n.map((t=>t.length))),height:n.length}}const u=t=>[...Array(t).keys()];class p{constructor(t){this._container=t}async init(){const t=this._container,i=t.actualOptions.canvasMask;if(!i?.enable)return;let o={pixels:[],height:0,width:0};const s=i.pixels.offset;if(i.image){const t=i.image.src;if(!t)return;o=await function(t,i){const o=new Image;o.crossOrigin="Anonymous";const s=new Promise(((t,s)=>{o.onerror=s,o.onload=()=>{const n=document.createElement("canvas");n.width=o.width,n.height=o.height;const r=n.getContext("2d");if(!r)return s(new Error(`${e.errorPrefix} Could not get canvas context`));r.drawImage(o,h.x,h.y,o.width,o.height,h.x,h.y,n.width,n.height),t(f(r,n,i))}}));return o.src=t,s}(t,s)}else if(i.text){const t=function(t,i){const o=document.createElement("canvas"),s=o.getContext("2d"),{font:n,text:r,lines:a,color:c}=t;if(!r||!s)return;const l=r.split(a.separator),d=(0,e.isNumber)(n.size)?`${n.size}px`:n.size,u=[];let p=0,g=0;for(const t of l){s.font=`${n.style??""} ${n.variant??""} ${n.weight??""} ${d} ${n.family}`;const e=s.measureText(t),i={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};p=Math.max(p||0,i.width),g+=i.height+a.spacing,u.push(i)}o.width=p,o.height=g;let x=0;for(const t of u)s.font=`${n.style??""} ${n.variant??""} ${n.weight??""} ${d} ${n.family}`,s.fillStyle=c,s.fillText(t.text,h.x,x+t.measure.actualBoundingBoxAscent),x+=t.height+a.spacing;return f(s,o,i)}(i.text,s);if(!t)return;o=t}else if(i.element??i.selector){const t=i.element??(i.selector&&document.querySelector(i.selector));if(!t)return;const e=t.getContext("2d");if(!e)return;o=f(e,t,s)}d(t,o,i.position,i.scale,i.override,i.pixels.filter)}}class g{constructor(){this.id="canvasMask"}getPlugin(t){return new p(t)}loadOptions(t,e){if(!this.needsPlugin(t)&&!this.needsPlugin(e))return;let i=t.canvasMask;void 0===i?.load&&(t.canvasMask=i=new l),i.load(e?.canvasMask)}needsPlugin(t){return t?.canvasMask?.enable??!1}}async function x(t,e=!0){await t.addPlugin(new g,e)}})(),s})()));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
/*! tsParticles Canvas Mask Plugin v3.0
|
|
1
|
+
/*! tsParticles Canvas Mask Plugin v3.1.0 by Matteo Bruni */
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { Engine, IContainerPlugin } from "@tsparticles/engine";
|
|
2
1
|
import type { CanvasMaskContainer } from "./types.js";
|
|
2
|
+
import type { IContainerPlugin } from "@tsparticles/engine";
|
|
3
3
|
export declare class CanvasMaskInstance implements IContainerPlugin {
|
|
4
4
|
private readonly _container;
|
|
5
|
-
|
|
6
|
-
constructor(container: CanvasMaskContainer, engine: Engine);
|
|
5
|
+
constructor(container: CanvasMaskContainer);
|
|
7
6
|
init(): Promise<void>;
|
|
8
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type IOptionLoader, type IRgba, type RecursivePartial } from "@tsparticles/engine";
|
|
2
2
|
import type { ICanvasMaskPixels } from "../Interfaces/ICanvasMaskPixels.js";
|
|
3
3
|
export declare class CanvasMaskPixels implements ICanvasMaskPixels, IOptionLoader<ICanvasMaskPixels> {
|
|
4
4
|
filter: (pixel: IRgba) => boolean;
|
package/types/utils.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { type Container, type ICoordinates, type IDimension, type IRgba } from "@tsparticles/engine";
|
|
2
2
|
import type { ICanvasMaskOverride } from "./Options/Interfaces/ICanvasMaskOverride.js";
|
|
3
3
|
import type { TextMask } from "./Options/Classes/TextMask.js";
|
|
4
|
-
export
|
|
4
|
+
export interface CanvasPixelData {
|
|
5
5
|
height: number;
|
|
6
6
|
pixels: IRgba[][];
|
|
7
7
|
width: number;
|
|
8
|
-
}
|
|
8
|
+
}
|
|
9
9
|
export declare function addParticlesFromCanvasPixels(container: Container, data: CanvasPixelData, position: ICoordinates, scale: number, override: ICanvasMaskOverride, filter: (pixel: IRgba) => boolean): void;
|
|
10
10
|
export declare function getCanvasImageData(ctx: CanvasRenderingContext2D, size: IDimension, offset: number, clear?: boolean): CanvasPixelData;
|
|
11
11
|
export declare function getImageData(src: string, offset: number): Promise<CanvasPixelData>;
|
|
@@ -12,9 +12,8 @@
|
|
|
12
12
|
exports.CanvasMaskInstance = void 0;
|
|
13
13
|
const utils_js_1 = require("./utils.js");
|
|
14
14
|
class CanvasMaskInstance {
|
|
15
|
-
constructor(container
|
|
15
|
+
constructor(container) {
|
|
16
16
|
this._container = container;
|
|
17
|
-
this._engine = engine;
|
|
18
17
|
}
|
|
19
18
|
async init() {
|
|
20
19
|
const container = this._container, options = container.actualOptions.canvasMask;
|
|
@@ -42,8 +41,8 @@
|
|
|
42
41
|
}
|
|
43
42
|
pixelData = data;
|
|
44
43
|
}
|
|
45
|
-
else if (options.element
|
|
46
|
-
const canvas = options.element
|
|
44
|
+
else if (options.element ?? options.selector) {
|
|
45
|
+
const canvas = options.element ?? (options.selector && document.querySelector(options.selector));
|
|
47
46
|
if (!canvas) {
|
|
48
47
|
return;
|
|
49
48
|
}
|
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.CanvasMaskPixels = void 0;
|
|
13
13
|
const engine_1 = require("@tsparticles/engine");
|
|
14
|
+
const minAlpha = 0;
|
|
14
15
|
class CanvasMaskPixels {
|
|
15
16
|
constructor() {
|
|
16
|
-
this.filter = (pixel) => pixel.a >
|
|
17
|
+
this.filter = (pixel) => pixel.a > minAlpha;
|
|
17
18
|
this.offset = 4;
|
|
18
19
|
}
|
|
19
20
|
load(data) {
|
package/umd/index.js
CHANGED
|
@@ -13,12 +13,11 @@
|
|
|
13
13
|
const CanvasMask_js_1 = require("./Options/Classes/CanvasMask.js");
|
|
14
14
|
const CanvasMaskInstance_js_1 = require("./CanvasMaskInstance.js");
|
|
15
15
|
class CanvasMaskPlugin {
|
|
16
|
-
constructor(
|
|
16
|
+
constructor() {
|
|
17
17
|
this.id = "canvasMask";
|
|
18
|
-
this._engine = engine;
|
|
19
18
|
}
|
|
20
19
|
getPlugin(container) {
|
|
21
|
-
return new CanvasMaskInstance_js_1.CanvasMaskInstance(container
|
|
20
|
+
return new CanvasMaskInstance_js_1.CanvasMaskInstance(container);
|
|
22
21
|
}
|
|
23
22
|
loadOptions(options, source) {
|
|
24
23
|
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
@@ -35,7 +34,7 @@
|
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
async function loadCanvasMaskPlugin(engine, refresh = true) {
|
|
38
|
-
await engine.addPlugin(new CanvasMaskPlugin(
|
|
37
|
+
await engine.addPlugin(new CanvasMaskPlugin(), refresh);
|
|
39
38
|
}
|
|
40
39
|
exports.loadCanvasMaskPlugin = loadCanvasMaskPlugin;
|
|
41
40
|
});
|
package/umd/utils.js
CHANGED
|
@@ -11,15 +11,19 @@
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.getTextData = exports.getImageData = exports.getCanvasImageData = exports.addParticlesFromCanvasPixels = void 0;
|
|
13
13
|
const engine_1 = require("@tsparticles/engine");
|
|
14
|
+
const half = 0.5, origin = {
|
|
15
|
+
x: 0,
|
|
16
|
+
y: 0,
|
|
17
|
+
}, defaultWidth = 0;
|
|
14
18
|
function addParticlesFromCanvasPixels(container, data, position, scale, override, filter) {
|
|
15
19
|
const { height, width } = data, numPixels = height * width, indexArray = shuffle(range(numPixels)), maxParticles = Math.min(numPixels, container.actualOptions.particles.number.value), canvasSize = container.canvas.size;
|
|
16
20
|
let selectedPixels = 0;
|
|
17
21
|
const positionOffset = {
|
|
18
|
-
x: (canvasSize.width * position.x) /
|
|
19
|
-
y: (canvasSize.height * position.y) /
|
|
22
|
+
x: (canvasSize.width * position.x) / engine_1.percentDenominator - width * scale * half,
|
|
23
|
+
y: (canvasSize.height * position.y) / engine_1.percentDenominator - height * scale * half,
|
|
20
24
|
};
|
|
21
25
|
while (selectedPixels < maxParticles && indexArray.length) {
|
|
22
|
-
const nextIndex = indexArray.pop()
|
|
26
|
+
const defaultIndex = 0, nextIndex = indexArray.pop() ?? defaultIndex, pixelPos = {
|
|
23
27
|
x: nextIndex % width,
|
|
24
28
|
y: Math.floor(nextIndex / width),
|
|
25
29
|
}, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = filter(pixel);
|
|
@@ -46,9 +50,9 @@
|
|
|
46
50
|
}
|
|
47
51
|
exports.addParticlesFromCanvasPixels = addParticlesFromCanvasPixels;
|
|
48
52
|
function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
49
|
-
const imageData = ctx.getImageData(
|
|
53
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
50
54
|
if (clear) {
|
|
51
|
-
ctx.clearRect(
|
|
55
|
+
ctx.clearRect(origin.x, origin.y, size.width, size.height);
|
|
52
56
|
}
|
|
53
57
|
const pixels = [];
|
|
54
58
|
for (let i = 0; i < imageData.length; i += offset) {
|
|
@@ -59,11 +63,17 @@
|
|
|
59
63
|
if (!pixels[pos.y]) {
|
|
60
64
|
pixels[pos.y] = [];
|
|
61
65
|
}
|
|
66
|
+
const indexesOffset = {
|
|
67
|
+
r: 0,
|
|
68
|
+
g: 1,
|
|
69
|
+
b: 2,
|
|
70
|
+
a: 3,
|
|
71
|
+
}, alphaFactor = 255;
|
|
62
72
|
pixels[pos.y][pos.x] = {
|
|
63
|
-
r: imageData[i],
|
|
64
|
-
g: imageData[i +
|
|
65
|
-
b: imageData[i +
|
|
66
|
-
a: imageData[i +
|
|
73
|
+
r: imageData[i + indexesOffset.r],
|
|
74
|
+
g: imageData[i + indexesOffset.g],
|
|
75
|
+
b: imageData[i + indexesOffset.b],
|
|
76
|
+
a: imageData[i + indexesOffset.a] / alphaFactor,
|
|
67
77
|
};
|
|
68
78
|
}
|
|
69
79
|
return {
|
|
@@ -86,7 +96,7 @@
|
|
|
86
96
|
if (!context) {
|
|
87
97
|
return reject(new Error(`${engine_1.errorPrefix} Could not get canvas context`));
|
|
88
98
|
}
|
|
89
|
-
context.drawImage(image,
|
|
99
|
+
context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
|
|
90
100
|
resolve(getCanvasImageData(context, canvas, offset));
|
|
91
101
|
};
|
|
92
102
|
});
|
|
@@ -102,14 +112,14 @@
|
|
|
102
112
|
const lines = text.split(linesOptions.separator), fontSize = (0, engine_1.isNumber)(font.size) ? `${font.size}px` : font.size, linesData = [];
|
|
103
113
|
let maxWidth = 0, totalHeight = 0;
|
|
104
114
|
for (const line of lines) {
|
|
105
|
-
context.font = `${font.style
|
|
115
|
+
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
|
|
106
116
|
const measure = context.measureText(line), lineData = {
|
|
107
117
|
measure,
|
|
108
118
|
text: line,
|
|
109
119
|
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
110
120
|
width: measure.width,
|
|
111
121
|
};
|
|
112
|
-
maxWidth = Math.max(maxWidth ||
|
|
122
|
+
maxWidth = Math.max(maxWidth || defaultWidth, lineData.width);
|
|
113
123
|
totalHeight += lineData.height + linesOptions.spacing;
|
|
114
124
|
linesData.push(lineData);
|
|
115
125
|
}
|
|
@@ -117,16 +127,17 @@
|
|
|
117
127
|
canvas.height = totalHeight;
|
|
118
128
|
let currentHeight = 0;
|
|
119
129
|
for (const line of linesData) {
|
|
120
|
-
context.font = `${font.style
|
|
130
|
+
context.font = `${font.style ?? ""} ${font.variant ?? ""} ${font.weight ?? ""} ${fontSize} ${font.family}`;
|
|
121
131
|
context.fillStyle = color;
|
|
122
|
-
context.fillText(line.text,
|
|
132
|
+
context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
123
133
|
currentHeight += line.height + linesOptions.spacing;
|
|
124
134
|
}
|
|
125
135
|
return getCanvasImageData(context, canvas, offset);
|
|
126
136
|
}
|
|
127
137
|
exports.getTextData = getTextData;
|
|
128
138
|
function shuffle(array) {
|
|
129
|
-
|
|
139
|
+
const lengthOffset = 1, minIndex = 0;
|
|
140
|
+
for (let currentIndex = array.length - lengthOffset; currentIndex >= minIndex; currentIndex--) {
|
|
130
141
|
const randomIndex = Math.floor((0, engine_1.getRandom)() * currentIndex);
|
|
131
142
|
[array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
|
|
132
143
|
}
|