@tsparticles/plugin-emitters-shape-canvas 3.0.3 → 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/EmittersCanvasShape.js +12 -12
- package/browser/Options/Classes/EmittersCanvasShapeOptions.js +2 -1
- package/browser/index.js +1 -2
- package/browser/utils.js +20 -10
- package/cjs/EmittersCanvasShape.js +12 -12
- package/cjs/Options/Classes/EmittersCanvasShapeOptions.js +2 -1
- package/cjs/index.js +1 -2
- package/cjs/utils.js +20 -10
- package/esm/EmittersCanvasShape.js +12 -12
- package/esm/Options/Classes/EmittersCanvasShapeOptions.js +2 -1
- package/esm/index.js +1 -2
- package/esm/utils.js +20 -10
- package/package.json +3 -3
- package/report.html +2 -2
- package/tsparticles.plugin.emitters.shape.canvas.js +42 -26
- package/tsparticles.plugin.emitters.shape.canvas.min.js +1 -1
- package/tsparticles.plugin.emitters.shape.canvas.min.js.LICENSE.txt +1 -1
- package/types/types.d.ts +4 -4
- package/types/utils.d.ts +1 -1
- package/umd/EmittersCanvasShape.js +12 -12
- package/umd/Options/Classes/EmittersCanvasShapeOptions.js +2 -1
- package/umd/index.js +1 -2
- package/umd/utils.js +20 -10
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { EmitterShapeBase } from "@tsparticles/plugin-emitters";
|
|
2
2
|
import { getRandom, isFunction, isString } from "@tsparticles/engine";
|
|
3
3
|
import { getCanvasImageData, getImageData, getTextData } from "./utils.js";
|
|
4
|
+
const maxRetries = 100, half = 0.5;
|
|
4
5
|
export class EmittersCanvasShape extends EmitterShapeBase {
|
|
5
6
|
constructor(position, size, fill, options) {
|
|
6
7
|
super(position, size, fill, options);
|
|
7
|
-
const filter = options.filter;
|
|
8
|
-
let filterFunc = (pixel) => pixel.a >
|
|
8
|
+
const filter = options.filter, minAlpha = 0;
|
|
9
|
+
let filterFunc = (pixel) => pixel.a > minAlpha;
|
|
9
10
|
if (filter !== undefined) {
|
|
10
11
|
if (isString(filter)) {
|
|
11
12
|
if (Object.hasOwn(window, filter)) {
|
|
@@ -44,8 +45,8 @@ export class EmittersCanvasShape extends EmitterShapeBase {
|
|
|
44
45
|
}
|
|
45
46
|
pixelData = data;
|
|
46
47
|
}
|
|
47
|
-
else if (element
|
|
48
|
-
const canvas = element
|
|
48
|
+
else if (element ?? selector) {
|
|
49
|
+
const canvas = element ?? (selector && document.querySelector(selector));
|
|
49
50
|
if (!canvas) {
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
@@ -61,12 +62,11 @@ export class EmittersCanvasShape extends EmitterShapeBase {
|
|
|
61
62
|
this.pixelData = pixelData;
|
|
62
63
|
}
|
|
63
64
|
async randomPosition() {
|
|
64
|
-
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
y: position.y - (height * scale) / 2,
|
|
65
|
+
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
|
|
66
|
+
x: position.x - width * scale * half,
|
|
67
|
+
y: position.y - height * scale * half,
|
|
68
68
|
};
|
|
69
|
-
for (let i = 0; i <
|
|
69
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
70
70
|
const nextIndex = Math.floor(getRandom() * width * height), pixelPos = {
|
|
71
71
|
x: nextIndex % width,
|
|
72
72
|
y: Math.floor(nextIndex / width),
|
|
@@ -74,16 +74,16 @@ export class EmittersCanvasShape extends EmitterShapeBase {
|
|
|
74
74
|
if (!shouldCreateParticle) {
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
|
-
return {
|
|
77
|
+
return Promise.resolve({
|
|
78
78
|
position: {
|
|
79
79
|
x: pixelPos.x * scale + positionOffset.x,
|
|
80
80
|
y: pixelPos.y * scale + positionOffset.y,
|
|
81
81
|
},
|
|
82
82
|
color: { ...pixel },
|
|
83
83
|
opacity: pixel.a,
|
|
84
|
-
};
|
|
84
|
+
});
|
|
85
85
|
}
|
|
86
|
-
return null;
|
|
86
|
+
return Promise.resolve(null);
|
|
87
87
|
}
|
|
88
88
|
resize(position, size) {
|
|
89
89
|
super.resize(position, size);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { PixelsOptions } from "./PixelsOptions.js";
|
|
2
2
|
import { TextOptions } from "./TextOptions.js";
|
|
3
|
+
const minAlpha = 0;
|
|
3
4
|
export class EmittersCanvasShapeOptions {
|
|
4
5
|
constructor() {
|
|
5
|
-
this.filter = (pixel) => pixel.a >
|
|
6
|
+
this.filter = (pixel) => pixel.a > minAlpha;
|
|
6
7
|
this.pixels = new PixelsOptions();
|
|
7
8
|
this.scale = 1;
|
|
8
9
|
this.selector = "";
|
package/browser/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { EmittersCanvasShapeGenerator } from "./EmittersCanvasShapeGenerator.js";
|
|
2
2
|
export async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
3
3
|
const emittersEngine = engine;
|
|
4
|
-
emittersEngine.addEmitterShapeGenerator
|
|
5
|
-
emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator());
|
|
4
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
|
|
6
5
|
await emittersEngine.refresh(refresh);
|
|
7
6
|
}
|
package/browser/utils.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { errorPrefix, isNumber } from "@tsparticles/engine";
|
|
2
|
+
const origin = {
|
|
3
|
+
x: 0,
|
|
4
|
+
y: 0,
|
|
5
|
+
}, minWidth = 0;
|
|
2
6
|
export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
3
|
-
const imageData = ctx.getImageData(
|
|
7
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
4
8
|
if (clear) {
|
|
5
|
-
ctx.clearRect(
|
|
9
|
+
ctx.clearRect(origin.x, origin.y, size.width, size.height);
|
|
6
10
|
}
|
|
7
11
|
const pixels = [];
|
|
8
12
|
for (let i = 0; i < imageData.length; i += offset) {
|
|
@@ -13,11 +17,17 @@ export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
|
13
17
|
if (!pixels[pos.y]) {
|
|
14
18
|
pixels[pos.y] = [];
|
|
15
19
|
}
|
|
20
|
+
const indexesOffset = {
|
|
21
|
+
r: 0,
|
|
22
|
+
g: 1,
|
|
23
|
+
b: 2,
|
|
24
|
+
a: 3,
|
|
25
|
+
}, alphaFactor = 255;
|
|
16
26
|
pixels[pos.y][pos.x] = {
|
|
17
|
-
r: imageData[i],
|
|
18
|
-
g: imageData[i +
|
|
19
|
-
b: imageData[i +
|
|
20
|
-
a: imageData[i +
|
|
27
|
+
r: imageData[i + indexesOffset.r],
|
|
28
|
+
g: imageData[i + indexesOffset.g],
|
|
29
|
+
b: imageData[i + indexesOffset.b],
|
|
30
|
+
a: imageData[i + indexesOffset.a] / alphaFactor,
|
|
21
31
|
};
|
|
22
32
|
}
|
|
23
33
|
return {
|
|
@@ -39,7 +49,7 @@ export function getImageData(src, offset) {
|
|
|
39
49
|
if (!context) {
|
|
40
50
|
return reject(new Error(`${errorPrefix} Could not get canvas context`));
|
|
41
51
|
}
|
|
42
|
-
context.drawImage(image,
|
|
52
|
+
context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
|
|
43
53
|
resolve(getCanvasImageData(context, canvas, offset));
|
|
44
54
|
};
|
|
45
55
|
});
|
|
@@ -61,7 +71,7 @@ export function getTextData(textOptions, offset, fill) {
|
|
|
61
71
|
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
62
72
|
width: measure.width,
|
|
63
73
|
};
|
|
64
|
-
maxWidth = Math.max(maxWidth ||
|
|
74
|
+
maxWidth = Math.max(maxWidth || minWidth, lineData.width);
|
|
65
75
|
totalHeight += lineData.height + linesOptions.spacing;
|
|
66
76
|
linesData.push(lineData);
|
|
67
77
|
}
|
|
@@ -72,11 +82,11 @@ export function getTextData(textOptions, offset, fill) {
|
|
|
72
82
|
context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
|
|
73
83
|
if (fill) {
|
|
74
84
|
context.fillStyle = color;
|
|
75
|
-
context.fillText(line.text,
|
|
85
|
+
context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
76
86
|
}
|
|
77
87
|
else {
|
|
78
88
|
context.strokeStyle = color;
|
|
79
|
-
context.strokeText(line.text,
|
|
89
|
+
context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
80
90
|
}
|
|
81
91
|
currentHeight += line.height + linesOptions.spacing;
|
|
82
92
|
}
|
|
@@ -4,11 +4,12 @@ exports.EmittersCanvasShape = void 0;
|
|
|
4
4
|
const plugin_emitters_1 = require("@tsparticles/plugin-emitters");
|
|
5
5
|
const engine_1 = require("@tsparticles/engine");
|
|
6
6
|
const utils_js_1 = require("./utils.js");
|
|
7
|
+
const maxRetries = 100, half = 0.5;
|
|
7
8
|
class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
|
|
8
9
|
constructor(position, size, fill, options) {
|
|
9
10
|
super(position, size, fill, options);
|
|
10
|
-
const filter = options.filter;
|
|
11
|
-
let filterFunc = (pixel) => pixel.a >
|
|
11
|
+
const filter = options.filter, minAlpha = 0;
|
|
12
|
+
let filterFunc = (pixel) => pixel.a > minAlpha;
|
|
12
13
|
if (filter !== undefined) {
|
|
13
14
|
if ((0, engine_1.isString)(filter)) {
|
|
14
15
|
if (Object.hasOwn(window, filter)) {
|
|
@@ -47,8 +48,8 @@ class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
|
|
|
47
48
|
}
|
|
48
49
|
pixelData = data;
|
|
49
50
|
}
|
|
50
|
-
else if (element
|
|
51
|
-
const canvas = element
|
|
51
|
+
else if (element ?? selector) {
|
|
52
|
+
const canvas = element ?? (selector && document.querySelector(selector));
|
|
52
53
|
if (!canvas) {
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
@@ -64,12 +65,11 @@ class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
|
|
|
64
65
|
this.pixelData = pixelData;
|
|
65
66
|
}
|
|
66
67
|
async randomPosition() {
|
|
67
|
-
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
y: position.y - (height * scale) / 2,
|
|
68
|
+
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
|
|
69
|
+
x: position.x - width * scale * half,
|
|
70
|
+
y: position.y - height * scale * half,
|
|
71
71
|
};
|
|
72
|
-
for (let i = 0; i <
|
|
72
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
73
73
|
const nextIndex = Math.floor((0, engine_1.getRandom)() * width * height), pixelPos = {
|
|
74
74
|
x: nextIndex % width,
|
|
75
75
|
y: Math.floor(nextIndex / width),
|
|
@@ -77,16 +77,16 @@ class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
|
|
|
77
77
|
if (!shouldCreateParticle) {
|
|
78
78
|
continue;
|
|
79
79
|
}
|
|
80
|
-
return {
|
|
80
|
+
return Promise.resolve({
|
|
81
81
|
position: {
|
|
82
82
|
x: pixelPos.x * scale + positionOffset.x,
|
|
83
83
|
y: pixelPos.y * scale + positionOffset.y,
|
|
84
84
|
},
|
|
85
85
|
color: { ...pixel },
|
|
86
86
|
opacity: pixel.a,
|
|
87
|
-
};
|
|
87
|
+
});
|
|
88
88
|
}
|
|
89
|
-
return null;
|
|
89
|
+
return Promise.resolve(null);
|
|
90
90
|
}
|
|
91
91
|
resize(position, size) {
|
|
92
92
|
super.resize(position, size);
|
|
@@ -3,9 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.EmittersCanvasShapeOptions = void 0;
|
|
4
4
|
const PixelsOptions_js_1 = require("./PixelsOptions.js");
|
|
5
5
|
const TextOptions_js_1 = require("./TextOptions.js");
|
|
6
|
+
const minAlpha = 0;
|
|
6
7
|
class EmittersCanvasShapeOptions {
|
|
7
8
|
constructor() {
|
|
8
|
-
this.filter = (pixel) => pixel.a >
|
|
9
|
+
this.filter = (pixel) => pixel.a > minAlpha;
|
|
9
10
|
this.pixels = new PixelsOptions_js_1.PixelsOptions();
|
|
10
11
|
this.scale = 1;
|
|
11
12
|
this.selector = "";
|
package/cjs/index.js
CHANGED
|
@@ -4,8 +4,7 @@ exports.loadEmittersShapeCanvas = void 0;
|
|
|
4
4
|
const EmittersCanvasShapeGenerator_js_1 = require("./EmittersCanvasShapeGenerator.js");
|
|
5
5
|
async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
6
6
|
const emittersEngine = engine;
|
|
7
|
-
emittersEngine.addEmitterShapeGenerator
|
|
8
|
-
emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
|
|
7
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
|
|
9
8
|
await emittersEngine.refresh(refresh);
|
|
10
9
|
}
|
|
11
10
|
exports.loadEmittersShapeCanvas = loadEmittersShapeCanvas;
|
package/cjs/utils.js
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getTextData = exports.getImageData = exports.getCanvasImageData = void 0;
|
|
4
4
|
const engine_1 = require("@tsparticles/engine");
|
|
5
|
+
const origin = {
|
|
6
|
+
x: 0,
|
|
7
|
+
y: 0,
|
|
8
|
+
}, minWidth = 0;
|
|
5
9
|
function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
6
|
-
const imageData = ctx.getImageData(
|
|
10
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
7
11
|
if (clear) {
|
|
8
|
-
ctx.clearRect(
|
|
12
|
+
ctx.clearRect(origin.x, origin.y, size.width, size.height);
|
|
9
13
|
}
|
|
10
14
|
const pixels = [];
|
|
11
15
|
for (let i = 0; i < imageData.length; i += offset) {
|
|
@@ -16,11 +20,17 @@ function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
|
16
20
|
if (!pixels[pos.y]) {
|
|
17
21
|
pixels[pos.y] = [];
|
|
18
22
|
}
|
|
23
|
+
const indexesOffset = {
|
|
24
|
+
r: 0,
|
|
25
|
+
g: 1,
|
|
26
|
+
b: 2,
|
|
27
|
+
a: 3,
|
|
28
|
+
}, alphaFactor = 255;
|
|
19
29
|
pixels[pos.y][pos.x] = {
|
|
20
|
-
r: imageData[i],
|
|
21
|
-
g: imageData[i +
|
|
22
|
-
b: imageData[i +
|
|
23
|
-
a: imageData[i +
|
|
30
|
+
r: imageData[i + indexesOffset.r],
|
|
31
|
+
g: imageData[i + indexesOffset.g],
|
|
32
|
+
b: imageData[i + indexesOffset.b],
|
|
33
|
+
a: imageData[i + indexesOffset.a] / alphaFactor,
|
|
24
34
|
};
|
|
25
35
|
}
|
|
26
36
|
return {
|
|
@@ -43,7 +53,7 @@ function getImageData(src, offset) {
|
|
|
43
53
|
if (!context) {
|
|
44
54
|
return reject(new Error(`${engine_1.errorPrefix} Could not get canvas context`));
|
|
45
55
|
}
|
|
46
|
-
context.drawImage(image,
|
|
56
|
+
context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
|
|
47
57
|
resolve(getCanvasImageData(context, canvas, offset));
|
|
48
58
|
};
|
|
49
59
|
});
|
|
@@ -66,7 +76,7 @@ function getTextData(textOptions, offset, fill) {
|
|
|
66
76
|
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
67
77
|
width: measure.width,
|
|
68
78
|
};
|
|
69
|
-
maxWidth = Math.max(maxWidth ||
|
|
79
|
+
maxWidth = Math.max(maxWidth || minWidth, lineData.width);
|
|
70
80
|
totalHeight += lineData.height + linesOptions.spacing;
|
|
71
81
|
linesData.push(lineData);
|
|
72
82
|
}
|
|
@@ -77,11 +87,11 @@ function getTextData(textOptions, offset, fill) {
|
|
|
77
87
|
context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
|
|
78
88
|
if (fill) {
|
|
79
89
|
context.fillStyle = color;
|
|
80
|
-
context.fillText(line.text,
|
|
90
|
+
context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
81
91
|
}
|
|
82
92
|
else {
|
|
83
93
|
context.strokeStyle = color;
|
|
84
|
-
context.strokeText(line.text,
|
|
94
|
+
context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
85
95
|
}
|
|
86
96
|
currentHeight += line.height + linesOptions.spacing;
|
|
87
97
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { EmitterShapeBase } from "@tsparticles/plugin-emitters";
|
|
2
2
|
import { getRandom, isFunction, isString } from "@tsparticles/engine";
|
|
3
3
|
import { getCanvasImageData, getImageData, getTextData } from "./utils.js";
|
|
4
|
+
const maxRetries = 100, half = 0.5;
|
|
4
5
|
export class EmittersCanvasShape extends EmitterShapeBase {
|
|
5
6
|
constructor(position, size, fill, options) {
|
|
6
7
|
super(position, size, fill, options);
|
|
7
|
-
const filter = options.filter;
|
|
8
|
-
let filterFunc = (pixel) => pixel.a >
|
|
8
|
+
const filter = options.filter, minAlpha = 0;
|
|
9
|
+
let filterFunc = (pixel) => pixel.a > minAlpha;
|
|
9
10
|
if (filter !== undefined) {
|
|
10
11
|
if (isString(filter)) {
|
|
11
12
|
if (Object.hasOwn(window, filter)) {
|
|
@@ -44,8 +45,8 @@ export class EmittersCanvasShape extends EmitterShapeBase {
|
|
|
44
45
|
}
|
|
45
46
|
pixelData = data;
|
|
46
47
|
}
|
|
47
|
-
else if (element
|
|
48
|
-
const canvas = element
|
|
48
|
+
else if (element ?? selector) {
|
|
49
|
+
const canvas = element ?? (selector && document.querySelector(selector));
|
|
49
50
|
if (!canvas) {
|
|
50
51
|
return;
|
|
51
52
|
}
|
|
@@ -61,12 +62,11 @@ export class EmittersCanvasShape extends EmitterShapeBase {
|
|
|
61
62
|
this.pixelData = pixelData;
|
|
62
63
|
}
|
|
63
64
|
async randomPosition() {
|
|
64
|
-
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
y: position.y - (height * scale) / 2,
|
|
65
|
+
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
|
|
66
|
+
x: position.x - width * scale * half,
|
|
67
|
+
y: position.y - height * scale * half,
|
|
68
68
|
};
|
|
69
|
-
for (let i = 0; i <
|
|
69
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
70
70
|
const nextIndex = Math.floor(getRandom() * width * height), pixelPos = {
|
|
71
71
|
x: nextIndex % width,
|
|
72
72
|
y: Math.floor(nextIndex / width),
|
|
@@ -74,16 +74,16 @@ export class EmittersCanvasShape extends EmitterShapeBase {
|
|
|
74
74
|
if (!shouldCreateParticle) {
|
|
75
75
|
continue;
|
|
76
76
|
}
|
|
77
|
-
return {
|
|
77
|
+
return Promise.resolve({
|
|
78
78
|
position: {
|
|
79
79
|
x: pixelPos.x * scale + positionOffset.x,
|
|
80
80
|
y: pixelPos.y * scale + positionOffset.y,
|
|
81
81
|
},
|
|
82
82
|
color: { ...pixel },
|
|
83
83
|
opacity: pixel.a,
|
|
84
|
-
};
|
|
84
|
+
});
|
|
85
85
|
}
|
|
86
|
-
return null;
|
|
86
|
+
return Promise.resolve(null);
|
|
87
87
|
}
|
|
88
88
|
resize(position, size) {
|
|
89
89
|
super.resize(position, size);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { PixelsOptions } from "./PixelsOptions.js";
|
|
2
2
|
import { TextOptions } from "./TextOptions.js";
|
|
3
|
+
const minAlpha = 0;
|
|
3
4
|
export class EmittersCanvasShapeOptions {
|
|
4
5
|
constructor() {
|
|
5
|
-
this.filter = (pixel) => pixel.a >
|
|
6
|
+
this.filter = (pixel) => pixel.a > minAlpha;
|
|
6
7
|
this.pixels = new PixelsOptions();
|
|
7
8
|
this.scale = 1;
|
|
8
9
|
this.selector = "";
|
package/esm/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { EmittersCanvasShapeGenerator } from "./EmittersCanvasShapeGenerator.js";
|
|
2
2
|
export async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
3
3
|
const emittersEngine = engine;
|
|
4
|
-
emittersEngine.addEmitterShapeGenerator
|
|
5
|
-
emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator());
|
|
4
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
|
|
6
5
|
await emittersEngine.refresh(refresh);
|
|
7
6
|
}
|
package/esm/utils.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { errorPrefix, isNumber } from "@tsparticles/engine";
|
|
2
|
+
const origin = {
|
|
3
|
+
x: 0,
|
|
4
|
+
y: 0,
|
|
5
|
+
}, minWidth = 0;
|
|
2
6
|
export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
3
|
-
const imageData = ctx.getImageData(
|
|
7
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
4
8
|
if (clear) {
|
|
5
|
-
ctx.clearRect(
|
|
9
|
+
ctx.clearRect(origin.x, origin.y, size.width, size.height);
|
|
6
10
|
}
|
|
7
11
|
const pixels = [];
|
|
8
12
|
for (let i = 0; i < imageData.length; i += offset) {
|
|
@@ -13,11 +17,17 @@ export function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
|
13
17
|
if (!pixels[pos.y]) {
|
|
14
18
|
pixels[pos.y] = [];
|
|
15
19
|
}
|
|
20
|
+
const indexesOffset = {
|
|
21
|
+
r: 0,
|
|
22
|
+
g: 1,
|
|
23
|
+
b: 2,
|
|
24
|
+
a: 3,
|
|
25
|
+
}, alphaFactor = 255;
|
|
16
26
|
pixels[pos.y][pos.x] = {
|
|
17
|
-
r: imageData[i],
|
|
18
|
-
g: imageData[i +
|
|
19
|
-
b: imageData[i +
|
|
20
|
-
a: imageData[i +
|
|
27
|
+
r: imageData[i + indexesOffset.r],
|
|
28
|
+
g: imageData[i + indexesOffset.g],
|
|
29
|
+
b: imageData[i + indexesOffset.b],
|
|
30
|
+
a: imageData[i + indexesOffset.a] / alphaFactor,
|
|
21
31
|
};
|
|
22
32
|
}
|
|
23
33
|
return {
|
|
@@ -39,7 +49,7 @@ export function getImageData(src, offset) {
|
|
|
39
49
|
if (!context) {
|
|
40
50
|
return reject(new Error(`${errorPrefix} Could not get canvas context`));
|
|
41
51
|
}
|
|
42
|
-
context.drawImage(image,
|
|
52
|
+
context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
|
|
43
53
|
resolve(getCanvasImageData(context, canvas, offset));
|
|
44
54
|
};
|
|
45
55
|
});
|
|
@@ -61,7 +71,7 @@ export function getTextData(textOptions, offset, fill) {
|
|
|
61
71
|
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
62
72
|
width: measure.width,
|
|
63
73
|
};
|
|
64
|
-
maxWidth = Math.max(maxWidth ||
|
|
74
|
+
maxWidth = Math.max(maxWidth || minWidth, lineData.width);
|
|
65
75
|
totalHeight += lineData.height + linesOptions.spacing;
|
|
66
76
|
linesData.push(lineData);
|
|
67
77
|
}
|
|
@@ -72,11 +82,11 @@ export function getTextData(textOptions, offset, fill) {
|
|
|
72
82
|
context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
|
|
73
83
|
if (fill) {
|
|
74
84
|
context.fillStyle = color;
|
|
75
|
-
context.fillText(line.text,
|
|
85
|
+
context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
76
86
|
}
|
|
77
87
|
else {
|
|
78
88
|
context.strokeStyle = color;
|
|
79
|
-
context.strokeText(line.text,
|
|
89
|
+
context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
80
90
|
}
|
|
81
91
|
currentHeight += line.height + linesOptions.spacing;
|
|
82
92
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsparticles/plugin-emitters-shape-canvas",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "tsParticles emitters shape canvas plugin",
|
|
5
5
|
"homepage": "https://particles.js.org",
|
|
6
6
|
"repository": {
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
"./package.json": "./package.json"
|
|
101
101
|
},
|
|
102
102
|
"dependencies": {
|
|
103
|
-
"@tsparticles/engine": "^3.0
|
|
104
|
-
"@tsparticles/plugin-emitters": "^3.0
|
|
103
|
+
"@tsparticles/engine": "^3.1.0",
|
|
104
|
+
"@tsparticles/plugin-emitters": "^3.1.0"
|
|
105
105
|
},
|
|
106
106
|
"publishConfig": {
|
|
107
107
|
"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-emitters-shape-canvas [
|
|
6
|
+
<title>@tsparticles/plugin-emitters-shape-canvas [13 Jan 2024 at 23:10]</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.emitters.shape.canvas.js","isAsset":true,"statSize":
|
|
34
|
+
window.chartData = [{"label":"tsparticles.plugin.emitters.shape.canvas.js","isAsset":true,"statSize":9718,"parsedSize":13934,"gzipSize":3694,"groups":[{"label":"dist/browser","path":"./dist/browser","statSize":9634,"groups":[{"id":806,"label":"index.js + 8 modules (concatenated)","path":"./dist/browser/index.js + 8 modules (concatenated)","statSize":9634,"parsedSize":13934,"gzipSize":3694,"concatenated":true,"groups":[{"label":"dist/browser","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser","statSize":9634,"groups":[{"id":null,"label":"index.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/index.js","statSize":320,"parsedSize":462,"gzipSize":122,"inaccurateSizes":true},{"id":null,"label":"EmittersCanvasShapeGenerator.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/EmittersCanvasShapeGenerator.js","statSize":414,"parsedSize":598,"gzipSize":158,"inaccurateSizes":true},{"label":"Options/Classes","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes","statSize":2538,"groups":[{"id":null,"label":"EmittersCanvasShapeOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/EmittersCanvasShapeOptions.js","statSize":855,"parsedSize":1236,"gzipSize":327,"inaccurateSizes":true},{"id":null,"label":"PixelsOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/PixelsOptions.js","statSize":205,"parsedSize":296,"gzipSize":78,"inaccurateSizes":true},{"id":null,"label":"TextOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextOptions.js","statSize":555,"parsedSize":802,"gzipSize":212,"inaccurateSizes":true},{"id":null,"label":"TextFontOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextFontOptions.js","statSize":599,"parsedSize":866,"gzipSize":229,"inaccurateSizes":true},{"id":null,"label":"TextLinesOptions.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/Options/Classes/TextLinesOptions.js","statSize":324,"parsedSize":468,"gzipSize":124,"inaccurateSizes":true}],"parsedSize":3670,"gzipSize":973,"inaccurateSizes":true},{"id":null,"label":"EmittersCanvasShape.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/EmittersCanvasShape.js","statSize":2946,"parsedSize":4260,"gzipSize":1129,"inaccurateSizes":true},{"id":null,"label":"utils.js","path":"./dist/browser/index.js + 8 modules (concatenated)/dist/browser/utils.js","statSize":3416,"parsedSize":4940,"gzipSize":1309,"inaccurateSizes":true}],"parsedSize":13934,"gzipSize":3694,"inaccurateSizes":true}]}],"parsedSize":13934,"gzipSize":3694},{"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},{"label":"plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles","path":"./plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles","statSize":42,"groups":[{"id":68,"label":"plugin-emitters\",\"root\":\"window\"}","path":"./plugin-emitters\",\"commonjs2\":\"@tsparticles/plugin-emitters\",\"amd\":\"@tsparticles/plugin-emitters\",\"root\":\"window\"}","statSize":42}],"parsedSize":0,"gzipSize":0}],"isInitialByEntrypoint":{"tsparticles.plugin.emitters.shape.canvas":true}}];
|
|
35
35
|
window.entrypoints = ["tsparticles.plugin.emitters.shape.canvas","tsparticles.plugin.emitters.shape.canvas.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')
|
|
@@ -107,10 +107,15 @@ var plugin_emitters_root_window_ = __webpack_require__(68);
|
|
|
107
107
|
var engine_root_window_ = __webpack_require__(533);
|
|
108
108
|
;// CONCATENATED MODULE: ./dist/browser/utils.js
|
|
109
109
|
|
|
110
|
+
const origin = {
|
|
111
|
+
x: 0,
|
|
112
|
+
y: 0
|
|
113
|
+
},
|
|
114
|
+
minWidth = 0;
|
|
110
115
|
function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
111
|
-
const imageData = ctx.getImageData(
|
|
116
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
112
117
|
if (clear) {
|
|
113
|
-
ctx.clearRect(
|
|
118
|
+
ctx.clearRect(origin.x, origin.y, size.width, size.height);
|
|
114
119
|
}
|
|
115
120
|
const pixels = [];
|
|
116
121
|
for (let i = 0; i < imageData.length; i += offset) {
|
|
@@ -122,11 +127,18 @@ function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
|
122
127
|
if (!pixels[pos.y]) {
|
|
123
128
|
pixels[pos.y] = [];
|
|
124
129
|
}
|
|
130
|
+
const indexesOffset = {
|
|
131
|
+
r: 0,
|
|
132
|
+
g: 1,
|
|
133
|
+
b: 2,
|
|
134
|
+
a: 3
|
|
135
|
+
},
|
|
136
|
+
alphaFactor = 255;
|
|
125
137
|
pixels[pos.y][pos.x] = {
|
|
126
|
-
r: imageData[i],
|
|
127
|
-
g: imageData[i +
|
|
128
|
-
b: imageData[i +
|
|
129
|
-
a: imageData[i +
|
|
138
|
+
r: imageData[i + indexesOffset.r],
|
|
139
|
+
g: imageData[i + indexesOffset.g],
|
|
140
|
+
b: imageData[i + indexesOffset.b],
|
|
141
|
+
a: imageData[i + indexesOffset.a] / alphaFactor
|
|
130
142
|
};
|
|
131
143
|
}
|
|
132
144
|
return {
|
|
@@ -148,7 +160,7 @@ function getImageData(src, offset) {
|
|
|
148
160
|
if (!context) {
|
|
149
161
|
return reject(new Error(`${engine_root_window_.errorPrefix} Could not get canvas context`));
|
|
150
162
|
}
|
|
151
|
-
context.drawImage(image,
|
|
163
|
+
context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
|
|
152
164
|
resolve(getCanvasImageData(context, canvas, offset));
|
|
153
165
|
};
|
|
154
166
|
});
|
|
@@ -181,7 +193,7 @@ function getTextData(textOptions, offset, fill) {
|
|
|
181
193
|
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
182
194
|
width: measure.width
|
|
183
195
|
};
|
|
184
|
-
maxWidth = Math.max(maxWidth ||
|
|
196
|
+
maxWidth = Math.max(maxWidth || minWidth, lineData.width);
|
|
185
197
|
totalHeight += lineData.height + linesOptions.spacing;
|
|
186
198
|
linesData.push(lineData);
|
|
187
199
|
}
|
|
@@ -192,10 +204,10 @@ function getTextData(textOptions, offset, fill) {
|
|
|
192
204
|
context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
|
|
193
205
|
if (fill) {
|
|
194
206
|
context.fillStyle = color;
|
|
195
|
-
context.fillText(line.text,
|
|
207
|
+
context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
196
208
|
} else {
|
|
197
209
|
context.strokeStyle = color;
|
|
198
|
-
context.strokeText(line.text,
|
|
210
|
+
context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
199
211
|
}
|
|
200
212
|
currentHeight += line.height + linesOptions.spacing;
|
|
201
213
|
}
|
|
@@ -205,11 +217,14 @@ function getTextData(textOptions, offset, fill) {
|
|
|
205
217
|
|
|
206
218
|
|
|
207
219
|
|
|
220
|
+
const maxRetries = 100,
|
|
221
|
+
half = 0.5;
|
|
208
222
|
class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase {
|
|
209
223
|
constructor(position, size, fill, options) {
|
|
210
224
|
super(position, size, fill, options);
|
|
211
|
-
const filter = options.filter
|
|
212
|
-
|
|
225
|
+
const filter = options.filter,
|
|
226
|
+
minAlpha = 0;
|
|
227
|
+
let filterFunc = pixel => pixel.a > minAlpha;
|
|
213
228
|
if (filter !== undefined) {
|
|
214
229
|
if ((0,engine_root_window_.isString)(filter)) {
|
|
215
230
|
if (Object.hasOwn(window, filter)) {
|
|
@@ -251,8 +266,8 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
|
|
|
251
266
|
return;
|
|
252
267
|
}
|
|
253
268
|
pixelData = data;
|
|
254
|
-
} else if (element
|
|
255
|
-
const canvas = element
|
|
269
|
+
} else if (element ?? selector) {
|
|
270
|
+
const canvas = element ?? (selector && document.querySelector(selector));
|
|
256
271
|
if (!canvas) {
|
|
257
272
|
return;
|
|
258
273
|
}
|
|
@@ -274,12 +289,12 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
|
|
|
274
289
|
} = this.pixelData,
|
|
275
290
|
data = this.pixelData,
|
|
276
291
|
position = this.position,
|
|
277
|
-
scale = this.scale
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
for (let i = 0; i <
|
|
292
|
+
scale = this.scale,
|
|
293
|
+
positionOffset = {
|
|
294
|
+
x: position.x - width * scale * half,
|
|
295
|
+
y: position.y - height * scale * half
|
|
296
|
+
};
|
|
297
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
283
298
|
const nextIndex = Math.floor((0,engine_root_window_.getRandom)() * width * height),
|
|
284
299
|
pixelPos = {
|
|
285
300
|
x: nextIndex % width,
|
|
@@ -290,7 +305,7 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
|
|
|
290
305
|
if (!shouldCreateParticle) {
|
|
291
306
|
continue;
|
|
292
307
|
}
|
|
293
|
-
return {
|
|
308
|
+
return Promise.resolve({
|
|
294
309
|
position: {
|
|
295
310
|
x: pixelPos.x * scale + positionOffset.x,
|
|
296
311
|
y: pixelPos.y * scale + positionOffset.y
|
|
@@ -299,9 +314,9 @@ class EmittersCanvasShape extends plugin_emitters_root_window_.EmitterShapeBase
|
|
|
299
314
|
...pixel
|
|
300
315
|
},
|
|
301
316
|
opacity: pixel.a
|
|
302
|
-
};
|
|
317
|
+
});
|
|
303
318
|
}
|
|
304
|
-
return null;
|
|
319
|
+
return Promise.resolve(null);
|
|
305
320
|
}
|
|
306
321
|
resize(position, size) {
|
|
307
322
|
super.resize(position, size);
|
|
@@ -396,9 +411,10 @@ class TextOptions {
|
|
|
396
411
|
;// CONCATENATED MODULE: ./dist/browser/Options/Classes/EmittersCanvasShapeOptions.js
|
|
397
412
|
|
|
398
413
|
|
|
414
|
+
const minAlpha = 0;
|
|
399
415
|
class EmittersCanvasShapeOptions {
|
|
400
416
|
constructor() {
|
|
401
|
-
this.filter = pixel => pixel.a >
|
|
417
|
+
this.filter = pixel => pixel.a > minAlpha;
|
|
402
418
|
this.pixels = new PixelsOptions();
|
|
403
419
|
this.scale = 1;
|
|
404
420
|
this.selector = "";
|
|
@@ -441,7 +457,7 @@ class EmittersCanvasShapeGenerator {
|
|
|
441
457
|
|
|
442
458
|
async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
443
459
|
const emittersEngine = engine;
|
|
444
|
-
emittersEngine.addEmitterShapeGenerator
|
|
460
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
|
|
445
461
|
await emittersEngine.refresh(refresh);
|
|
446
462
|
}
|
|
447
463
|
})();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! For license information please see tsparticles.plugin.emitters.shape.canvas.min.js.LICENSE.txt */
|
|
2
|
-
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/plugin-emitters","@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine")):e(t.window,t.window);for(var s in i)("object"==typeof exports?exports:t)[s]=i[s]}}(this,((t,e)=>(()=>{"use strict";var i={533:t=>{t.exports=e},68:e=>{e.exports=t}},s={};function o(t){var e=s[t];if(void 0!==e)return e.exports;var r=s[t]={exports:{}};return i[t](r,r.exports,o),r.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 r={};return(()=>{o.r(r),o.d(r,{loadEmittersShapeCanvas:()=>
|
|
2
|
+
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine"));else if("function"==typeof define&&define.amd)define(["@tsparticles/plugin-emitters","@tsparticles/engine"],e);else{var i="object"==typeof exports?e(require("@tsparticles/plugin-emitters"),require("@tsparticles/engine")):e(t.window,t.window);for(var s in i)("object"==typeof exports?exports:t)[s]=i[s]}}(this,((t,e)=>(()=>{"use strict";var i={533:t=>{t.exports=e},68:e=>{e.exports=t}},s={};function o(t){var e=s[t];if(void 0!==e)return e.exports;var r=s[t]={exports:{}};return i[t](r,r.exports,o),r.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 r={};return(()=>{o.r(r),o.d(r,{loadEmittersShapeCanvas:()=>u});var t=o(68),e=o(533);const i={x:0,y:0};function s(t,e,s,o=!0){const r=t.getImageData(i.x,i.y,e.width,e.height).data;o&&t.clearRect(i.x,i.y,e.width,e.height);const n=[];for(let t=0;t<r.length;t+=s){const i=t/s,o={x:i%e.width,y:Math.floor(i/e.width)};n[o.y]||(n[o.y]=[]);const a={r:0,g:1,b:2,a:3},l=255;n[o.y][o.x]={r:r[t+a.r],g:r[t+a.g],b:r[t+a.b],a:r[t+a.a]/l}}return{pixels:n,width:Math.min(...n.map((t=>t.length))),height:n.length}}class n extends t.EmitterShapeBase{constructor(t,i,s,o){super(t,i,s,o);const r=o.filter;let n=t=>t.a>0;if(void 0!==r)if((0,e.isString)(r)){if(Object.hasOwn(window,r)){const t=window[r];(0,e.isFunction)(t)&&(n=t)}}else n=r;this.filter=n,this.scale=o.scale,this.pixelData={pixels:[],height:0,width:0}}async init(){let t;const o=this.options,r=o.selector,n=o.pixels,a=o.image,l=o.element,c=o.text,h=n.offset;if(a){const o=a.src;if(!o)return;t=await function(t,o){const r=new Image;r.crossOrigin="Anonymous";const n=new Promise(((t,n)=>{r.onerror=n,r.onload=()=>{const a=document.createElement("canvas");a.width=r.width,a.height=r.height;const l=a.getContext("2d");if(!l)return n(new Error(`${e.errorPrefix} Could not get canvas context`));l.drawImage(r,i.x,i.y,r.width,r.height,i.x,i.y,a.width,a.height),t(s(l,a,o))}}));return r.src=t,n}(o,h)}else if(c){const o=function(t,o,r){const n=document.createElement("canvas"),a=n.getContext("2d"),{font:l,text:c,lines:h,color:d}=t;if(!c||!a)return;const f=c.split(h.separator),u=(0,e.isNumber)(l.size)?`${l.size}px`:l.size,p=[];let x=0,g=0;for(const t of f){a.font=`${l.style||""} ${l.variant||""} ${l.weight||""} ${u} ${l.family}`;const e=a.measureText(t),i={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};x=Math.max(x||0,i.width),g+=i.height+h.spacing,p.push(i)}n.width=x,n.height=g;let m=0;for(const t of p)a.font=`${l.style||""} ${l.variant||""} ${l.weight||""} ${u} ${l.family}`,r?(a.fillStyle=d,a.fillText(t.text,i.x,m+t.measure.actualBoundingBoxAscent)):(a.strokeStyle=d,a.strokeText(t.text,i.x,m+t.measure.actualBoundingBoxAscent)),m+=t.height+h.spacing;return s(a,n,o)}(c,h,this.fill);if(!o)return;t=o}else if(l??r){const e=l??(r&&document.querySelector(r));if(!e)return;const i=e.getContext("2d");if(!i)return;t=s(i,e,h)}t&&(this.pixelData=t)}async randomPosition(){const{height:t,width:i}=this.pixelData,s=this.pixelData,o=this.position,r=this.scale,n=o.x-i*r*.5,a=o.y-t*r*.5;for(let o=0;o<100;o++){const o=Math.floor((0,e.getRandom)()*i*t),l={x:o%i,y:Math.floor(o/i)},c=s.pixels[l.y][l.x];if(this.filter(c))return Promise.resolve({position:{x:l.x*r+n,y:l.y*r+a},color:{...c},opacity:c.a})}return Promise.resolve(null)}resize(t,e){super.resize(t,e)}}class a{constructor(){this.offset=4}load(t){t&&void 0!==t.offset&&(this.offset=t.offset)}}class l{constructor(){this.family="Verdana",this.size=32,this.style="",this.variant="",this.weight=""}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 c{constructor(){this.separator="\n",this.spacing=0}load(t){t&&(void 0!==t.separator&&(this.separator=t.separator),void 0!==t.spacing&&(this.spacing=t.spacing))}}class h{constructor(){this.color="#000000",this.font=new l,this.lines=new c,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 d{constructor(){this.filter=t=>t.a>0,this.pixels=new a,this.scale=1,this.selector="",this.text=new h}load(t){t&&(void 0!==t.element&&(this.element=t.element),void 0!==t.filter&&(this.filter=t.filter),this.pixels.load(t.pixels),void 0!==t.scale&&(this.scale=t.scale),void 0!==t.selector&&(this.selector=t.selector),void 0!==t.image&&(this.image=t.image),this.text.load(t.text))}}class f{generate(t,e,i,s){const o=new d;return o.load(s),new n(t,e,i,o)}}async function u(t,e=!0){const i=t;i.addEmitterShapeGenerator?.("canvas",new f),await i.refresh(e)}})(),r})()));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
/*! tsParticles Emitters Shape Canvas Plugin v3.0
|
|
1
|
+
/*! tsParticles Emitters Shape Canvas Plugin v3.1.0 by Matteo Bruni */
|
package/types/types.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { IRgba } from "@tsparticles/engine";
|
|
2
|
-
export
|
|
2
|
+
export interface CanvasPixelData {
|
|
3
3
|
height: number;
|
|
4
4
|
pixels: IRgba[][];
|
|
5
5
|
width: number;
|
|
6
|
-
}
|
|
7
|
-
export
|
|
6
|
+
}
|
|
7
|
+
export interface TextLineData {
|
|
8
8
|
height: number;
|
|
9
9
|
measure: TextMetrics;
|
|
10
10
|
text: string;
|
|
11
11
|
width: number;
|
|
12
|
-
}
|
|
12
|
+
}
|
package/types/utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CanvasPixelData } from "./types.js";
|
|
2
|
-
import type
|
|
2
|
+
import { type IDimension } from "@tsparticles/engine";
|
|
3
3
|
import type { TextOptions } from "./Options/Classes/TextOptions.js";
|
|
4
4
|
export declare function getCanvasImageData(ctx: CanvasRenderingContext2D, size: IDimension, offset: number, clear?: boolean): CanvasPixelData;
|
|
5
5
|
export declare function getImageData(src: string, offset: number): Promise<CanvasPixelData>;
|
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
const plugin_emitters_1 = require("@tsparticles/plugin-emitters");
|
|
14
14
|
const engine_1 = require("@tsparticles/engine");
|
|
15
15
|
const utils_js_1 = require("./utils.js");
|
|
16
|
+
const maxRetries = 100, half = 0.5;
|
|
16
17
|
class EmittersCanvasShape extends plugin_emitters_1.EmitterShapeBase {
|
|
17
18
|
constructor(position, size, fill, options) {
|
|
18
19
|
super(position, size, fill, options);
|
|
19
|
-
const filter = options.filter;
|
|
20
|
-
let filterFunc = (pixel) => pixel.a >
|
|
20
|
+
const filter = options.filter, minAlpha = 0;
|
|
21
|
+
let filterFunc = (pixel) => pixel.a > minAlpha;
|
|
21
22
|
if (filter !== undefined) {
|
|
22
23
|
if ((0, engine_1.isString)(filter)) {
|
|
23
24
|
if (Object.hasOwn(window, filter)) {
|
|
@@ -56,8 +57,8 @@
|
|
|
56
57
|
}
|
|
57
58
|
pixelData = data;
|
|
58
59
|
}
|
|
59
|
-
else if (element
|
|
60
|
-
const canvas = element
|
|
60
|
+
else if (element ?? selector) {
|
|
61
|
+
const canvas = element ?? (selector && document.querySelector(selector));
|
|
61
62
|
if (!canvas) {
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
@@ -73,12 +74,11 @@
|
|
|
73
74
|
this.pixelData = pixelData;
|
|
74
75
|
}
|
|
75
76
|
async randomPosition() {
|
|
76
|
-
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
y: position.y - (height * scale) / 2,
|
|
77
|
+
const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = {
|
|
78
|
+
x: position.x - width * scale * half,
|
|
79
|
+
y: position.y - height * scale * half,
|
|
80
80
|
};
|
|
81
|
-
for (let i = 0; i <
|
|
81
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
82
82
|
const nextIndex = Math.floor((0, engine_1.getRandom)() * width * height), pixelPos = {
|
|
83
83
|
x: nextIndex % width,
|
|
84
84
|
y: Math.floor(nextIndex / width),
|
|
@@ -86,16 +86,16 @@
|
|
|
86
86
|
if (!shouldCreateParticle) {
|
|
87
87
|
continue;
|
|
88
88
|
}
|
|
89
|
-
return {
|
|
89
|
+
return Promise.resolve({
|
|
90
90
|
position: {
|
|
91
91
|
x: pixelPos.x * scale + positionOffset.x,
|
|
92
92
|
y: pixelPos.y * scale + positionOffset.y,
|
|
93
93
|
},
|
|
94
94
|
color: { ...pixel },
|
|
95
95
|
opacity: pixel.a,
|
|
96
|
-
};
|
|
96
|
+
});
|
|
97
97
|
}
|
|
98
|
-
return null;
|
|
98
|
+
return Promise.resolve(null);
|
|
99
99
|
}
|
|
100
100
|
resize(position, size) {
|
|
101
101
|
super.resize(position, size);
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
exports.EmittersCanvasShapeOptions = void 0;
|
|
13
13
|
const PixelsOptions_js_1 = require("./PixelsOptions.js");
|
|
14
14
|
const TextOptions_js_1 = require("./TextOptions.js");
|
|
15
|
+
const minAlpha = 0;
|
|
15
16
|
class EmittersCanvasShapeOptions {
|
|
16
17
|
constructor() {
|
|
17
|
-
this.filter = (pixel) => pixel.a >
|
|
18
|
+
this.filter = (pixel) => pixel.a > minAlpha;
|
|
18
19
|
this.pixels = new PixelsOptions_js_1.PixelsOptions();
|
|
19
20
|
this.scale = 1;
|
|
20
21
|
this.selector = "";
|
package/umd/index.js
CHANGED
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
const EmittersCanvasShapeGenerator_js_1 = require("./EmittersCanvasShapeGenerator.js");
|
|
14
14
|
async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
15
15
|
const emittersEngine = engine;
|
|
16
|
-
emittersEngine.addEmitterShapeGenerator
|
|
17
|
-
emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
|
|
16
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
|
|
18
17
|
await emittersEngine.refresh(refresh);
|
|
19
18
|
}
|
|
20
19
|
exports.loadEmittersShapeCanvas = loadEmittersShapeCanvas;
|
package/umd/utils.js
CHANGED
|
@@ -11,10 +11,14 @@
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.getTextData = exports.getImageData = exports.getCanvasImageData = void 0;
|
|
13
13
|
const engine_1 = require("@tsparticles/engine");
|
|
14
|
+
const origin = {
|
|
15
|
+
x: 0,
|
|
16
|
+
y: 0,
|
|
17
|
+
}, minWidth = 0;
|
|
14
18
|
function getCanvasImageData(ctx, size, offset, clear = true) {
|
|
15
|
-
const imageData = ctx.getImageData(
|
|
19
|
+
const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;
|
|
16
20
|
if (clear) {
|
|
17
|
-
ctx.clearRect(
|
|
21
|
+
ctx.clearRect(origin.x, origin.y, size.width, size.height);
|
|
18
22
|
}
|
|
19
23
|
const pixels = [];
|
|
20
24
|
for (let i = 0; i < imageData.length; i += offset) {
|
|
@@ -25,11 +29,17 @@
|
|
|
25
29
|
if (!pixels[pos.y]) {
|
|
26
30
|
pixels[pos.y] = [];
|
|
27
31
|
}
|
|
32
|
+
const indexesOffset = {
|
|
33
|
+
r: 0,
|
|
34
|
+
g: 1,
|
|
35
|
+
b: 2,
|
|
36
|
+
a: 3,
|
|
37
|
+
}, alphaFactor = 255;
|
|
28
38
|
pixels[pos.y][pos.x] = {
|
|
29
|
-
r: imageData[i],
|
|
30
|
-
g: imageData[i +
|
|
31
|
-
b: imageData[i +
|
|
32
|
-
a: imageData[i +
|
|
39
|
+
r: imageData[i + indexesOffset.r],
|
|
40
|
+
g: imageData[i + indexesOffset.g],
|
|
41
|
+
b: imageData[i + indexesOffset.b],
|
|
42
|
+
a: imageData[i + indexesOffset.a] / alphaFactor,
|
|
33
43
|
};
|
|
34
44
|
}
|
|
35
45
|
return {
|
|
@@ -52,7 +62,7 @@
|
|
|
52
62
|
if (!context) {
|
|
53
63
|
return reject(new Error(`${engine_1.errorPrefix} Could not get canvas context`));
|
|
54
64
|
}
|
|
55
|
-
context.drawImage(image,
|
|
65
|
+
context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);
|
|
56
66
|
resolve(getCanvasImageData(context, canvas, offset));
|
|
57
67
|
};
|
|
58
68
|
});
|
|
@@ -75,7 +85,7 @@
|
|
|
75
85
|
height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,
|
|
76
86
|
width: measure.width,
|
|
77
87
|
};
|
|
78
|
-
maxWidth = Math.max(maxWidth ||
|
|
88
|
+
maxWidth = Math.max(maxWidth || minWidth, lineData.width);
|
|
79
89
|
totalHeight += lineData.height + linesOptions.spacing;
|
|
80
90
|
linesData.push(lineData);
|
|
81
91
|
}
|
|
@@ -86,11 +96,11 @@
|
|
|
86
96
|
context.font = `${font.style || ""} ${font.variant || ""} ${font.weight || ""} ${fontSize} ${font.family}`;
|
|
87
97
|
if (fill) {
|
|
88
98
|
context.fillStyle = color;
|
|
89
|
-
context.fillText(line.text,
|
|
99
|
+
context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
90
100
|
}
|
|
91
101
|
else {
|
|
92
102
|
context.strokeStyle = color;
|
|
93
|
-
context.strokeText(line.text,
|
|
103
|
+
context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);
|
|
94
104
|
}
|
|
95
105
|
currentHeight += line.height + linesOptions.spacing;
|
|
96
106
|
}
|