@tsparticles/plugin-emitters-shape-canvas 3.0.3 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/720.min.js +2 -0
- package/720.min.js.LICENSE.txt +1 -0
- package/browser/EmittersCanvasShape.js +12 -12
- package/browser/Options/Classes/EmittersCanvasShapeOptions.js +2 -1
- package/browser/index.js +2 -4
- package/browser/utils.js +20 -10
- package/cjs/EmittersCanvasShape.js +12 -12
- package/cjs/Options/Classes/EmittersCanvasShapeOptions.js +2 -1
- package/cjs/index.js +25 -4
- package/cjs/utils.js +20 -10
- package/dist_browser_EmittersCanvasShapeGenerator_js.js +100 -0
- package/esm/EmittersCanvasShape.js +12 -12
- package/esm/Options/Classes/EmittersCanvasShapeOptions.js +2 -1
- package/esm/index.js +2 -4
- package/esm/utils.js +20 -10
- package/package.json +3 -3
- package/report.html +3 -3
- package/tsparticles.plugin.emitters.shape.canvas.js +246 -362
- 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 +27 -5
- package/umd/utils.js +20 -10
package/720.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 720.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_plugin_emitters_shape_canvas=this.webpackChunk_tsparticles_plugin_emitters_shape_canvas||[]).push([[720],{720:(t,e,i)=>{i.d(e,{EmittersCanvasShapeGenerator:()=>g});var s=i(68),o=i(533);const n={x:0,y:0};function a(t,e,i,s=!0){const o=t.getImageData(n.x,n.y,e.width,e.height).data;s&&t.clearRect(n.x,n.y,e.width,e.height);const a=[];for(let t=0;t<o.length;t+=i){const s=t/i,n={x:s%e.width,y:Math.floor(s/e.width)};a[n.y]||(a[n.y]=[]);const r={r:0,g:1,b:2,a:3},l=255;a[n.y][n.x]={r:o[t+r.r],g:o[t+r.g],b:o[t+r.b],a:o[t+r.a]/l}}return{pixels:a,width:Math.min(...a.map((t=>t.length))),height:a.length}}class r extends s.EmitterShapeBase{constructor(t,e,i,s){super(t,e,i,s);const n=s.filter;let a=t=>t.a>0;if(void 0!==n)if((0,o.isString)(n)){if(Object.hasOwn(window,n)){const t=window[n];(0,o.isFunction)(t)&&(a=t)}}else a=n;this.filter=a,this.scale=s.scale,this.pixelData={pixels:[],height:0,width:0}}async init(){let t;const e=this.options,i=e.selector,s=e.pixels,r=e.image,l=e.element,h=e.text,c=s.offset;if(r){const e=r.src;if(!e)return;t=await function(t,e){const i=new Image;i.crossOrigin="Anonymous";const s=new Promise(((t,s)=>{i.onerror=s,i.onload=()=>{const r=document.createElement("canvas");r.width=i.width,r.height=i.height;const l=r.getContext("2d");if(!l)return s(new Error(`${o.errorPrefix} Could not get canvas context`));l.drawImage(i,n.x,n.y,i.width,i.height,n.x,n.y,r.width,r.height),t(a(l,r,e))}}));return i.src=t,s}(e,c)}else if(h){const e=function(t,e,i){const s=document.createElement("canvas"),r=s.getContext("2d"),{font:l,text:h,lines:c,color:d}=t;if(!h||!r)return;const f=h.split(c.separator),g=(0,o.isNumber)(l.size)?`${l.size}px`:l.size,x=[];let u=0,p=0;for(const t of f){r.font=`${l.style||""} ${l.variant||""} ${l.weight||""} ${g} ${l.family}`;const e=r.measureText(t),i={measure:e,text:t,height:e.actualBoundingBoxAscent+e.actualBoundingBoxDescent,width:e.width};u=Math.max(u||0,i.width),p+=i.height+c.spacing,x.push(i)}s.width=u,s.height=p;let m=0;for(const t of x)r.font=`${l.style||""} ${l.variant||""} ${l.weight||""} ${g} ${l.family}`,i?(r.fillStyle=d,r.fillText(t.text,n.x,m+t.measure.actualBoundingBoxAscent)):(r.strokeStyle=d,r.strokeText(t.text,n.x,m+t.measure.actualBoundingBoxAscent)),m+=t.height+c.spacing;return a(r,s,e)}(h,c,this.fill);if(!e)return;t=e}else if(l??i){const e=l??(i&&document.querySelector(i));if(!e)return;const s=e.getContext("2d");if(!s)return;t=a(s,e,c)}t&&(this.pixelData=t)}async randomPosition(){const{height:t,width:e}=this.pixelData,i=this.pixelData,s=this.position,n=this.scale,a=s.x-e*n*.5,r=s.y-t*n*.5;for(let s=0;s<100;s++){const s=Math.floor((0,o.getRandom)()*e*t),l={x:s%e,y:Math.floor(s/e)},h=i.pixels[l.y][l.x];if(this.filter(h))return Promise.resolve({position:{x:l.x*n+a,y:l.y*n+r},color:{...h},opacity:h.a})}return Promise.resolve(null)}resize(t,e){super.resize(t,e)}}class l{constructor(){this.offset=4}load(t){t&&void 0!==t.offset&&(this.offset=t.offset)}}class h{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 d{constructor(){this.color="#000000",this.font=new h,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 f{constructor(){this.filter=t=>t.a>0,this.pixels=new l,this.scale=1,this.selector="",this.text=new d}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 g{generate(t,e,i,s){const o=new f;return o.load(s),new r(t,e,i,o)}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Emitters Shape Canvas Plugin v3.2.0 by Matteo Bruni */
|
|
@@ -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,5 @@
|
|
|
1
|
-
import { EmittersCanvasShapeGenerator } from "./EmittersCanvasShapeGenerator.js";
|
|
2
1
|
export async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
3
|
-
const emittersEngine = engine;
|
|
4
|
-
emittersEngine.addEmitterShapeGenerator
|
|
5
|
-
emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator());
|
|
2
|
+
const emittersEngine = engine, { EmittersCanvasShapeGenerator } = await import("./EmittersCanvasShapeGenerator.js");
|
|
3
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
|
|
6
4
|
await emittersEngine.refresh(refresh);
|
|
7
5
|
}
|
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
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.loadEmittersShapeCanvas = void 0;
|
|
4
|
-
const EmittersCanvasShapeGenerator_js_1 = require("./EmittersCanvasShapeGenerator.js");
|
|
5
27
|
async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
6
|
-
const emittersEngine = engine;
|
|
7
|
-
emittersEngine.addEmitterShapeGenerator
|
|
8
|
-
emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator_js_1.EmittersCanvasShapeGenerator());
|
|
28
|
+
const emittersEngine = engine, { EmittersCanvasShapeGenerator } = await Promise.resolve().then(() => __importStar(require("./EmittersCanvasShapeGenerator.js")));
|
|
29
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
|
|
9
30
|
await emittersEngine.refresh(refresh);
|
|
10
31
|
}
|
|
11
32
|
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
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Author : Matteo Bruni
|
|
3
|
+
* MIT license: https://opensource.org/licenses/MIT
|
|
4
|
+
* Demo / Generator : https://particles.js.org/
|
|
5
|
+
* GitHub : https://www.github.com/matteobruni/tsparticles
|
|
6
|
+
* How to use? : Check the GitHub README
|
|
7
|
+
* v3.2.0
|
|
8
|
+
*/
|
|
9
|
+
"use strict";
|
|
10
|
+
/*
|
|
11
|
+
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
|
|
12
|
+
* This devtool is neither made for production nor for readable output files.
|
|
13
|
+
* It uses "eval()" calls to create a separate source file in the browser devtools.
|
|
14
|
+
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
15
|
+
* or disable the default devtool with "devtool: false".
|
|
16
|
+
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
17
|
+
*/
|
|
18
|
+
(this["webpackChunk_tsparticles_plugin_emitters_shape_canvas"] = this["webpackChunk_tsparticles_plugin_emitters_shape_canvas"] || []).push([["dist_browser_EmittersCanvasShapeGenerator_js"],{
|
|
19
|
+
|
|
20
|
+
/***/ "./dist/browser/EmittersCanvasShape.js":
|
|
21
|
+
/*!*********************************************!*\
|
|
22
|
+
!*** ./dist/browser/EmittersCanvasShape.js ***!
|
|
23
|
+
\*********************************************/
|
|
24
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
25
|
+
|
|
26
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ EmittersCanvasShape: () => (/* binding */ EmittersCanvasShape)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_plugin_emitters__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/plugin-emitters */ \"@tsparticles/plugin-emitters\");\n/* harmony import */ var _tsparticles_plugin_emitters__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_tsparticles_plugin_emitters__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils.js */ \"./dist/browser/utils.js\");\n\n\n\nconst maxRetries = 100,\n half = 0.5;\nclass EmittersCanvasShape extends _tsparticles_plugin_emitters__WEBPACK_IMPORTED_MODULE_0__.EmitterShapeBase {\n constructor(position, size, fill, options) {\n super(position, size, fill, options);\n const filter = options.filter,\n minAlpha = 0;\n let filterFunc = pixel => pixel.a > minAlpha;\n if (filter !== undefined) {\n if ((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__.isString)(filter)) {\n if (Object.hasOwn(window, filter)) {\n const wndFilter = window[filter];\n if ((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__.isFunction)(wndFilter)) {\n filterFunc = wndFilter;\n }\n }\n } else {\n filterFunc = filter;\n }\n }\n this.filter = filterFunc;\n this.scale = options.scale;\n this.pixelData = {\n pixels: [],\n height: 0,\n width: 0\n };\n }\n async init() {\n let pixelData;\n const options = this.options,\n selector = options.selector,\n pixels = options.pixels,\n image = options.image,\n element = options.element,\n text = options.text,\n offset = pixels.offset;\n if (image) {\n const url = image.src;\n if (!url) {\n return;\n }\n pixelData = await (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.getImageData)(url, offset);\n } else if (text) {\n const data = (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.getTextData)(text, offset, this.fill);\n if (!data) {\n return;\n }\n pixelData = data;\n } else if (element ?? selector) {\n const canvas = element ?? (selector && document.querySelector(selector));\n if (!canvas) {\n return;\n }\n const context = canvas.getContext(\"2d\");\n if (!context) {\n return;\n }\n pixelData = (0,_utils_js__WEBPACK_IMPORTED_MODULE_2__.getCanvasImageData)(context, canvas, offset);\n }\n if (!pixelData) {\n return;\n }\n this.pixelData = pixelData;\n }\n async randomPosition() {\n const {\n height,\n width\n } = this.pixelData,\n data = this.pixelData,\n position = this.position,\n scale = this.scale,\n positionOffset = {\n x: position.x - width * scale * half,\n y: position.y - height * scale * half\n };\n for (let i = 0; i < maxRetries; i++) {\n const nextIndex = Math.floor((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_1__.getRandom)() * width * height),\n pixelPos = {\n x: nextIndex % width,\n y: Math.floor(nextIndex / width)\n },\n pixel = data.pixels[pixelPos.y][pixelPos.x],\n shouldCreateParticle = this.filter(pixel);\n if (!shouldCreateParticle) {\n continue;\n }\n return Promise.resolve({\n position: {\n x: pixelPos.x * scale + positionOffset.x,\n y: pixelPos.y * scale + positionOffset.y\n },\n color: {\n ...pixel\n },\n opacity: pixel.a\n });\n }\n return Promise.resolve(null);\n }\n resize(position, size) {\n super.resize(position, size);\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/EmittersCanvasShape.js?");
|
|
27
|
+
|
|
28
|
+
/***/ }),
|
|
29
|
+
|
|
30
|
+
/***/ "./dist/browser/EmittersCanvasShapeGenerator.js":
|
|
31
|
+
/*!******************************************************!*\
|
|
32
|
+
!*** ./dist/browser/EmittersCanvasShapeGenerator.js ***!
|
|
33
|
+
\******************************************************/
|
|
34
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
35
|
+
|
|
36
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ EmittersCanvasShapeGenerator: () => (/* binding */ EmittersCanvasShapeGenerator)\n/* harmony export */ });\n/* harmony import */ var _EmittersCanvasShape_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./EmittersCanvasShape.js */ \"./dist/browser/EmittersCanvasShape.js\");\n/* harmony import */ var _Options_Classes_EmittersCanvasShapeOptions_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Options/Classes/EmittersCanvasShapeOptions.js */ \"./dist/browser/Options/Classes/EmittersCanvasShapeOptions.js\");\n\n\nclass EmittersCanvasShapeGenerator {\n generate(position, size, fill, options) {\n const shapeOptions = new _Options_Classes_EmittersCanvasShapeOptions_js__WEBPACK_IMPORTED_MODULE_0__.EmittersCanvasShapeOptions();\n shapeOptions.load(options);\n return new _EmittersCanvasShape_js__WEBPACK_IMPORTED_MODULE_1__.EmittersCanvasShape(position, size, fill, shapeOptions);\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/EmittersCanvasShapeGenerator.js?");
|
|
37
|
+
|
|
38
|
+
/***/ }),
|
|
39
|
+
|
|
40
|
+
/***/ "./dist/browser/Options/Classes/EmittersCanvasShapeOptions.js":
|
|
41
|
+
/*!********************************************************************!*\
|
|
42
|
+
!*** ./dist/browser/Options/Classes/EmittersCanvasShapeOptions.js ***!
|
|
43
|
+
\********************************************************************/
|
|
44
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
45
|
+
|
|
46
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ EmittersCanvasShapeOptions: () => (/* binding */ EmittersCanvasShapeOptions)\n/* harmony export */ });\n/* harmony import */ var _PixelsOptions_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PixelsOptions.js */ \"./dist/browser/Options/Classes/PixelsOptions.js\");\n/* harmony import */ var _TextOptions_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TextOptions.js */ \"./dist/browser/Options/Classes/TextOptions.js\");\n\n\nconst minAlpha = 0;\nclass EmittersCanvasShapeOptions {\n constructor() {\n this.filter = pixel => pixel.a > minAlpha;\n this.pixels = new _PixelsOptions_js__WEBPACK_IMPORTED_MODULE_0__.PixelsOptions();\n this.scale = 1;\n this.selector = \"\";\n this.text = new _TextOptions_js__WEBPACK_IMPORTED_MODULE_1__.TextOptions();\n }\n load(data) {\n if (!data) {\n return;\n }\n if (data.element !== undefined) {\n this.element = data.element;\n }\n if (data.filter !== undefined) {\n this.filter = data.filter;\n }\n this.pixels.load(data.pixels);\n if (data.scale !== undefined) {\n this.scale = data.scale;\n }\n if (data.selector !== undefined) {\n this.selector = data.selector;\n }\n if (data.image !== undefined) {\n this.image = data.image;\n }\n this.text.load(data.text);\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/Options/Classes/EmittersCanvasShapeOptions.js?");
|
|
47
|
+
|
|
48
|
+
/***/ }),
|
|
49
|
+
|
|
50
|
+
/***/ "./dist/browser/Options/Classes/PixelsOptions.js":
|
|
51
|
+
/*!*******************************************************!*\
|
|
52
|
+
!*** ./dist/browser/Options/Classes/PixelsOptions.js ***!
|
|
53
|
+
\*******************************************************/
|
|
54
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
55
|
+
|
|
56
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PixelsOptions: () => (/* binding */ PixelsOptions)\n/* harmony export */ });\nclass PixelsOptions {\n constructor() {\n this.offset = 4;\n }\n load(data) {\n if (!data) {\n return;\n }\n if (data.offset !== undefined) {\n this.offset = data.offset;\n }\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/Options/Classes/PixelsOptions.js?");
|
|
57
|
+
|
|
58
|
+
/***/ }),
|
|
59
|
+
|
|
60
|
+
/***/ "./dist/browser/Options/Classes/TextFontOptions.js":
|
|
61
|
+
/*!*********************************************************!*\
|
|
62
|
+
!*** ./dist/browser/Options/Classes/TextFontOptions.js ***!
|
|
63
|
+
\*********************************************************/
|
|
64
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
65
|
+
|
|
66
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TextFontOptions: () => (/* binding */ TextFontOptions)\n/* harmony export */ });\nclass TextFontOptions {\n constructor() {\n this.family = \"Verdana\";\n this.size = 32;\n this.style = \"\";\n this.variant = \"\";\n this.weight = \"\";\n }\n load(data) {\n if (!data) {\n return;\n }\n if (data.family !== undefined) {\n this.family = data.family;\n }\n if (data.size !== undefined) {\n this.size = data.size;\n }\n if (data.style !== undefined) {\n this.style = data.style;\n }\n if (data.variant !== undefined) {\n this.variant = data.variant;\n }\n if (data.weight !== undefined) {\n this.weight = data.weight;\n }\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/Options/Classes/TextFontOptions.js?");
|
|
67
|
+
|
|
68
|
+
/***/ }),
|
|
69
|
+
|
|
70
|
+
/***/ "./dist/browser/Options/Classes/TextLinesOptions.js":
|
|
71
|
+
/*!**********************************************************!*\
|
|
72
|
+
!*** ./dist/browser/Options/Classes/TextLinesOptions.js ***!
|
|
73
|
+
\**********************************************************/
|
|
74
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
75
|
+
|
|
76
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TextLinesOptions: () => (/* binding */ TextLinesOptions)\n/* harmony export */ });\nclass TextLinesOptions {\n constructor() {\n this.separator = \"\\n\";\n this.spacing = 0;\n }\n load(data) {\n if (!data) {\n return;\n }\n if (data.separator !== undefined) {\n this.separator = data.separator;\n }\n if (data.spacing !== undefined) {\n this.spacing = data.spacing;\n }\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/Options/Classes/TextLinesOptions.js?");
|
|
77
|
+
|
|
78
|
+
/***/ }),
|
|
79
|
+
|
|
80
|
+
/***/ "./dist/browser/Options/Classes/TextOptions.js":
|
|
81
|
+
/*!*****************************************************!*\
|
|
82
|
+
!*** ./dist/browser/Options/Classes/TextOptions.js ***!
|
|
83
|
+
\*****************************************************/
|
|
84
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
85
|
+
|
|
86
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ TextOptions: () => (/* binding */ TextOptions)\n/* harmony export */ });\n/* harmony import */ var _TextFontOptions_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./TextFontOptions.js */ \"./dist/browser/Options/Classes/TextFontOptions.js\");\n/* harmony import */ var _TextLinesOptions_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TextLinesOptions.js */ \"./dist/browser/Options/Classes/TextLinesOptions.js\");\n\n\nclass TextOptions {\n constructor() {\n this.color = \"#000000\";\n this.font = new _TextFontOptions_js__WEBPACK_IMPORTED_MODULE_0__.TextFontOptions();\n this.lines = new _TextLinesOptions_js__WEBPACK_IMPORTED_MODULE_1__.TextLinesOptions();\n this.text = \"\";\n }\n load(data) {\n if (!data) {\n return;\n }\n if (data.color !== undefined) {\n this.color = data.color;\n }\n this.font.load(data.font);\n this.lines.load(data.lines);\n if (data.text !== undefined) {\n this.text = data.text;\n }\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/Options/Classes/TextOptions.js?");
|
|
87
|
+
|
|
88
|
+
/***/ }),
|
|
89
|
+
|
|
90
|
+
/***/ "./dist/browser/utils.js":
|
|
91
|
+
/*!*******************************!*\
|
|
92
|
+
!*** ./dist/browser/utils.js ***!
|
|
93
|
+
\*******************************/
|
|
94
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
95
|
+
|
|
96
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getCanvasImageData: () => (/* binding */ getCanvasImageData),\n/* harmony export */ getImageData: () => (/* binding */ getImageData),\n/* harmony export */ getTextData: () => (/* binding */ getTextData)\n/* harmony export */ });\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @tsparticles/engine */ \"@tsparticles/engine\");\n/* harmony import */ var _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__);\n\nconst origin = {\n x: 0,\n y: 0\n },\n minWidth = 0;\nfunction getCanvasImageData(ctx, size, offset, clear = true) {\n const imageData = ctx.getImageData(origin.x, origin.y, size.width, size.height).data;\n if (clear) {\n ctx.clearRect(origin.x, origin.y, size.width, size.height);\n }\n const pixels = [];\n for (let i = 0; i < imageData.length; i += offset) {\n const idx = i / offset,\n pos = {\n x: idx % size.width,\n y: Math.floor(idx / size.width)\n };\n if (!pixels[pos.y]) {\n pixels[pos.y] = [];\n }\n const indexesOffset = {\n r: 0,\n g: 1,\n b: 2,\n a: 3\n },\n alphaFactor = 255;\n pixels[pos.y][pos.x] = {\n r: imageData[i + indexesOffset.r],\n g: imageData[i + indexesOffset.g],\n b: imageData[i + indexesOffset.b],\n a: imageData[i + indexesOffset.a] / alphaFactor\n };\n }\n return {\n pixels,\n width: Math.min(...pixels.map(row => row.length)),\n height: pixels.length\n };\n}\nfunction getImageData(src, offset) {\n const image = new Image();\n image.crossOrigin = \"Anonymous\";\n const p = new Promise((resolve, reject) => {\n image.onerror = reject;\n image.onload = () => {\n const canvas = document.createElement(\"canvas\");\n canvas.width = image.width;\n canvas.height = image.height;\n const context = canvas.getContext(\"2d\");\n if (!context) {\n return reject(new Error(`${_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.errorPrefix} Could not get canvas context`));\n }\n context.drawImage(image, origin.x, origin.y, image.width, image.height, origin.x, origin.y, canvas.width, canvas.height);\n resolve(getCanvasImageData(context, canvas, offset));\n };\n });\n image.src = src;\n return p;\n}\nfunction getTextData(textOptions, offset, fill) {\n const canvas = document.createElement(\"canvas\"),\n context = canvas.getContext(\"2d\"),\n {\n font,\n text,\n lines: linesOptions,\n color\n } = textOptions;\n if (!text || !context) {\n return;\n }\n const lines = text.split(linesOptions.separator),\n fontSize = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isNumber)(font.size) ? `${font.size}px` : font.size,\n linesData = [];\n let maxWidth = 0,\n totalHeight = 0;\n for (const line of lines) {\n context.font = `${font.style || \"\"} ${font.variant || \"\"} ${font.weight || \"\"} ${fontSize} ${font.family}`;\n const measure = context.measureText(line),\n lineData = {\n measure,\n text: line,\n height: measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent,\n width: measure.width\n };\n maxWidth = Math.max(maxWidth || minWidth, lineData.width);\n totalHeight += lineData.height + linesOptions.spacing;\n linesData.push(lineData);\n }\n canvas.width = maxWidth;\n canvas.height = totalHeight;\n let currentHeight = 0;\n for (const line of linesData) {\n context.font = `${font.style || \"\"} ${font.variant || \"\"} ${font.weight || \"\"} ${fontSize} ${font.family}`;\n if (fill) {\n context.fillStyle = color;\n context.fillText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);\n } else {\n context.strokeStyle = color;\n context.strokeText(line.text, origin.x, currentHeight + line.measure.actualBoundingBoxAscent);\n }\n currentHeight += line.height + linesOptions.spacing;\n }\n return getCanvasImageData(context, canvas, offset);\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-emitters-shape-canvas/./dist/browser/utils.js?");
|
|
97
|
+
|
|
98
|
+
/***/ })
|
|
99
|
+
|
|
100
|
+
}]);
|
|
@@ -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,5 @@
|
|
|
1
|
-
import { EmittersCanvasShapeGenerator } from "./EmittersCanvasShapeGenerator.js";
|
|
2
1
|
export async function loadEmittersShapeCanvas(engine, refresh = true) {
|
|
3
|
-
const emittersEngine = engine;
|
|
4
|
-
emittersEngine.addEmitterShapeGenerator
|
|
5
|
-
emittersEngine.addEmitterShapeGenerator("canvas", new EmittersCanvasShapeGenerator());
|
|
2
|
+
const emittersEngine = engine, { EmittersCanvasShapeGenerator } = await import("./EmittersCanvasShapeGenerator.js");
|
|
3
|
+
emittersEngine.addEmitterShapeGenerator?.("canvas", new EmittersCanvasShapeGenerator());
|
|
6
4
|
await emittersEngine.refresh(refresh);
|
|
7
5
|
}
|
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
|
}
|