@tsparticles/plugin-polygon-mask 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/PolygonMaskInstance.js +46 -38
- package/browser/utils.js +21 -10
- package/cjs/PolygonMaskInstance.js +45 -37
- package/cjs/utils.js +21 -10
- package/esm/PolygonMaskInstance.js +46 -38
- package/esm/utils.js +21 -10
- package/package.json +2 -2
- package/report.html +2 -2
- package/tsparticles.plugin.polygon-mask.js +83 -46
- package/tsparticles.plugin.polygon-mask.min.js +1 -1
- package/tsparticles.plugin.polygon-mask.min.js.LICENSE.txt +1 -1
- package/types/Options/Classes/PolygonMaskInline.d.ts +1 -2
- package/umd/PolygonMaskInstance.js +45 -37
- package/umd/utils.js +21 -10
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
exports.PolygonMaskInstance = void 0;
|
|
13
13
|
const engine_1 = require("@tsparticles/engine");
|
|
14
14
|
const utils_js_1 = require("./utils.js");
|
|
15
|
-
const noPolygonDataLoaded = `${engine_1.errorPrefix} No polygon data loaded.`, noPolygonFound = `${engine_1.errorPrefix} No polygon found, you need to specify SVG url in config
|
|
15
|
+
const noPolygonDataLoaded = `${engine_1.errorPrefix} No polygon data loaded.`, noPolygonFound = `${engine_1.errorPrefix} No polygon found, you need to specify SVG url in config.`, origin = {
|
|
16
|
+
x: 0,
|
|
17
|
+
y: 0,
|
|
18
|
+
}, half = 0.5, double = 2;
|
|
16
19
|
class PolygonMaskInstance {
|
|
17
20
|
constructor(container, engine) {
|
|
18
21
|
this._checkInsidePolygon = (position) => {
|
|
@@ -23,19 +26,20 @@
|
|
|
23
26
|
if (!this.raw) {
|
|
24
27
|
throw new Error(noPolygonFound);
|
|
25
28
|
}
|
|
26
|
-
const canvasSize = container.canvas.size, x = position?.x ?? (0, engine_1.getRandom)() * canvasSize.width, y = position?.y ?? (0, engine_1.getRandom)() * canvasSize.height;
|
|
29
|
+
const canvasSize = container.canvas.size, x = position?.x ?? (0, engine_1.getRandom)() * canvasSize.width, y = position?.y ?? (0, engine_1.getRandom)() * canvasSize.height, indexOffset = 1;
|
|
27
30
|
let inside = false;
|
|
28
|
-
for (let i = 0, j = this.raw.length -
|
|
31
|
+
for (let i = 0, j = this.raw.length - indexOffset; i < this.raw.length; j = i++) {
|
|
29
32
|
const pi = this.raw[i], pj = this.raw[j], intersect = pi.y > y !== pj.y > y && x < ((pj.x - pi.x) * (y - pi.y)) / (pj.y - pi.y) + pi.x;
|
|
30
33
|
if (intersect) {
|
|
31
34
|
inside = !inside;
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if (options.type === "inside") {
|
|
38
|
+
return inside;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return options.type === "outside" ? !inside : false;
|
|
42
|
+
}
|
|
39
43
|
};
|
|
40
44
|
this._createPath2D = () => {
|
|
41
45
|
const container = this._container, options = container.actualOptions.polygon;
|
|
@@ -57,13 +61,14 @@
|
|
|
57
61
|
else {
|
|
58
62
|
delete path.path2d;
|
|
59
63
|
}
|
|
60
|
-
if (path.path2d
|
|
64
|
+
if (path.path2d ?? !this.raw) {
|
|
61
65
|
continue;
|
|
62
66
|
}
|
|
63
67
|
path.path2d = new Path2D();
|
|
64
|
-
|
|
68
|
+
const firstIndex = 0, firstPoint = this.raw[firstIndex];
|
|
69
|
+
path.path2d.moveTo(firstPoint.x, firstPoint.y);
|
|
65
70
|
this.raw.forEach((pos, i) => {
|
|
66
|
-
if (i >
|
|
71
|
+
if (i > firstIndex) {
|
|
67
72
|
path.path2d?.lineTo(pos.x, pos.y);
|
|
68
73
|
}
|
|
69
74
|
});
|
|
@@ -75,7 +80,7 @@
|
|
|
75
80
|
if (!options) {
|
|
76
81
|
return;
|
|
77
82
|
}
|
|
78
|
-
const url = svgUrl
|
|
83
|
+
const url = svgUrl ?? options.url, forceDownload = force ?? false;
|
|
79
84
|
if (!url || (this.paths !== undefined && !forceDownload)) {
|
|
80
85
|
return this.raw;
|
|
81
86
|
}
|
|
@@ -101,11 +106,11 @@
|
|
|
101
106
|
if (!polygonMaskOptions) {
|
|
102
107
|
return;
|
|
103
108
|
}
|
|
104
|
-
if (!this.raw
|
|
109
|
+
if (!this.raw?.length || !this.paths?.length) {
|
|
105
110
|
throw new Error(noPolygonDataLoaded);
|
|
106
111
|
}
|
|
107
112
|
let offset = 0, point;
|
|
108
|
-
const totalLength = this.paths.reduce((tot, path) => tot + path.length,
|
|
113
|
+
const baseAccumulator = 0, totalLength = this.paths.reduce((tot, path) => tot + path.length, baseAccumulator), distance = totalLength / options.particles.number.value;
|
|
109
114
|
for (const path of this.paths) {
|
|
110
115
|
const pathDistance = distance * index - offset;
|
|
111
116
|
if (pathDistance <= path.length) {
|
|
@@ -118,12 +123,12 @@
|
|
|
118
123
|
}
|
|
119
124
|
const scale = this._scale;
|
|
120
125
|
return {
|
|
121
|
-
x: (point?.x ??
|
|
122
|
-
y: (point?.y ??
|
|
126
|
+
x: (point?.x ?? origin.x) * scale + (this.offset?.x ?? origin.x),
|
|
127
|
+
y: (point?.y ?? origin.y) * scale + (this.offset?.y ?? origin.y),
|
|
123
128
|
};
|
|
124
129
|
};
|
|
125
130
|
this._getPointByIndex = (index) => {
|
|
126
|
-
if (!this.raw
|
|
131
|
+
if (!this.raw?.length) {
|
|
127
132
|
throw new Error(noPolygonDataLoaded);
|
|
128
133
|
}
|
|
129
134
|
const coords = this.raw[index % this.raw.length];
|
|
@@ -133,7 +138,7 @@
|
|
|
133
138
|
};
|
|
134
139
|
};
|
|
135
140
|
this._getRandomPoint = () => {
|
|
136
|
-
if (!this.raw
|
|
141
|
+
if (!this.raw?.length) {
|
|
137
142
|
throw new Error(noPolygonDataLoaded);
|
|
138
143
|
}
|
|
139
144
|
const coords = (0, engine_1.itemFromArray)(this.raw);
|
|
@@ -147,13 +152,13 @@
|
|
|
147
152
|
if (!options) {
|
|
148
153
|
return;
|
|
149
154
|
}
|
|
150
|
-
if (!this.raw
|
|
155
|
+
if (!this.raw?.length || !this.paths?.length) {
|
|
151
156
|
throw new Error(noPolygonDataLoaded);
|
|
152
157
|
}
|
|
153
|
-
const path = (0, engine_1.itemFromArray)(this.paths), distance = Math.floor((0, engine_1.getRandom)() * path.length) +
|
|
158
|
+
const path = (0, engine_1.itemFromArray)(this.paths), offset = 1, distance = Math.floor((0, engine_1.getRandom)() * path.length) + offset, point = path.element.getPointAtLength(distance), scale = this._scale;
|
|
154
159
|
return {
|
|
155
|
-
x: point.x * scale + (this.offset?.x
|
|
156
|
-
y: point.y * scale + (this.offset?.y
|
|
160
|
+
x: point.x * scale + (this.offset?.x ?? origin.x),
|
|
161
|
+
y: point.y * scale + (this.offset?.y ?? origin.y),
|
|
157
162
|
};
|
|
158
163
|
};
|
|
159
164
|
this._initRawData = async (force) => {
|
|
@@ -191,7 +196,7 @@
|
|
|
191
196
|
if (!options) {
|
|
192
197
|
return;
|
|
193
198
|
}
|
|
194
|
-
const parser = new DOMParser(), doc = parser.parseFromString(xml, "image/svg+xml"), svg = doc.getElementsByTagName("svg")[
|
|
199
|
+
const parser = new DOMParser(), doc = parser.parseFromString(xml, "image/svg+xml"), firstIndex = 0, svg = doc.getElementsByTagName("svg")[firstIndex];
|
|
195
200
|
let svgPaths = svg.getElementsByTagName("path");
|
|
196
201
|
if (!svgPaths.length) {
|
|
197
202
|
svgPaths = doc.getElementsByTagName("path");
|
|
@@ -214,8 +219,8 @@
|
|
|
214
219
|
y: 50,
|
|
215
220
|
}, canvasSize = container.canvas.size;
|
|
216
221
|
this.offset = {
|
|
217
|
-
x: (canvasSize.width * position.x) /
|
|
218
|
-
y: (canvasSize.height * position.y) /
|
|
222
|
+
x: (canvasSize.width * position.x) / engine_1.percentDenominator - this.dimension.width * half,
|
|
223
|
+
y: (canvasSize.height * position.y) / engine_1.percentDenominator - this.dimension.height * half,
|
|
219
224
|
};
|
|
220
225
|
return (0, utils_js_1.parsePaths)(this.paths, scale, this.offset);
|
|
221
226
|
};
|
|
@@ -226,8 +231,8 @@
|
|
|
226
231
|
}
|
|
227
232
|
if (options.type === "inside" || options.type === "outside") {
|
|
228
233
|
let closest, dx, dy;
|
|
229
|
-
const pos = particle.getPosition(), radius = particle.getRadius();
|
|
230
|
-
for (let i = 0, j = this.raw.length -
|
|
234
|
+
const pos = particle.getPosition(), radius = particle.getRadius(), offset = 1;
|
|
235
|
+
for (let i = 0, j = this.raw.length - offset; i < this.raw.length; j = i++) {
|
|
231
236
|
const pi = this.raw[i], pj = this.raw[j];
|
|
232
237
|
closest = (0, utils_js_1.calcClosestPtOnSegment)(pi, pj, pos);
|
|
233
238
|
const dist = (0, engine_1.getDistances)(pos, closest);
|
|
@@ -238,7 +243,7 @@
|
|
|
238
243
|
}
|
|
239
244
|
}
|
|
240
245
|
if (closest && dx !== undefined && dy !== undefined && !this._checkInsidePolygon(pos)) {
|
|
241
|
-
const factor = { x: 1, y: 1 }, diameter = radius *
|
|
246
|
+
const factor = { x: 1, y: 1 }, diameter = radius * double, inverse = -1;
|
|
242
247
|
if (pos.x >= closest.x) {
|
|
243
248
|
factor.x = -1;
|
|
244
249
|
}
|
|
@@ -247,15 +252,15 @@
|
|
|
247
252
|
}
|
|
248
253
|
particle.position.x = closest.x + diameter * factor.x;
|
|
249
254
|
particle.position.y = closest.y + diameter * factor.y;
|
|
250
|
-
particle.velocity.mult(
|
|
255
|
+
particle.velocity.mult(inverse);
|
|
251
256
|
return true;
|
|
252
257
|
}
|
|
253
258
|
}
|
|
254
259
|
else if (options.type === "inline" && particle.initialPosition) {
|
|
255
260
|
const dist = (0, engine_1.getDistance)(particle.initialPosition, particle.getPosition()), { velocity } = particle;
|
|
256
261
|
if (dist > this._moveRadius) {
|
|
257
|
-
velocity.x = velocity.y
|
|
258
|
-
velocity.y = velocity.x
|
|
262
|
+
velocity.x = velocity.y * half - velocity.x;
|
|
263
|
+
velocity.y = velocity.x * half - velocity.y;
|
|
259
264
|
return true;
|
|
260
265
|
}
|
|
261
266
|
}
|
|
@@ -355,8 +360,8 @@
|
|
|
355
360
|
return this._polygonBounce(particle, delta, direction);
|
|
356
361
|
}
|
|
357
362
|
particlePosition(position) {
|
|
358
|
-
const options = this._container.actualOptions.polygon;
|
|
359
|
-
if (!(options?.enable && (this.raw?.length ??
|
|
363
|
+
const options = this._container.actualOptions.polygon, defaultLength = 0;
|
|
364
|
+
if (!(options?.enable && (this.raw?.length ?? defaultLength) > defaultLength)) {
|
|
360
365
|
return;
|
|
361
366
|
}
|
|
362
367
|
return (0, engine_1.deepExtend)({}, position ? position : this._randomPoint());
|
|
@@ -380,10 +385,13 @@
|
|
|
380
385
|
if (this.redrawTimeout) {
|
|
381
386
|
clearTimeout(this.redrawTimeout);
|
|
382
387
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
388
|
+
const timeout = 250;
|
|
389
|
+
this.redrawTimeout = window.setTimeout(() => {
|
|
390
|
+
void (async () => {
|
|
391
|
+
await this._initRawData(true);
|
|
392
|
+
await container.particles.redraw();
|
|
393
|
+
})();
|
|
394
|
+
}, timeout);
|
|
387
395
|
}
|
|
388
396
|
stop() {
|
|
389
397
|
delete this.raw;
|
package/umd/utils.js
CHANGED
|
@@ -11,13 +11,18 @@
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.segmentBounce = exports.calcClosestPtOnSegment = exports.parsePaths = exports.drawPolygonMaskPath = exports.drawPolygonMask = void 0;
|
|
13
13
|
const engine_1 = require("@tsparticles/engine");
|
|
14
|
+
const squareExp = 2, inSegmentRange = {
|
|
15
|
+
min: 0,
|
|
16
|
+
max: 1,
|
|
17
|
+
}, double = 2;
|
|
14
18
|
function drawPolygonMask(context, rawData, stroke) {
|
|
15
19
|
const color = (0, engine_1.rangeColorToRgb)(stroke.color);
|
|
16
20
|
if (!color) {
|
|
17
21
|
return;
|
|
18
22
|
}
|
|
23
|
+
const firstIndex = 0, firstItem = rawData[firstIndex];
|
|
19
24
|
context.beginPath();
|
|
20
|
-
context.moveTo(
|
|
25
|
+
context.moveTo(firstItem.x, firstItem.y);
|
|
21
26
|
for (const item of rawData) {
|
|
22
27
|
context.lineTo(item.x, item.y);
|
|
23
28
|
}
|
|
@@ -28,7 +33,13 @@
|
|
|
28
33
|
}
|
|
29
34
|
exports.drawPolygonMask = drawPolygonMask;
|
|
30
35
|
function drawPolygonMaskPath(context, path, stroke, position) {
|
|
31
|
-
|
|
36
|
+
const defaultTransform = {
|
|
37
|
+
a: 1,
|
|
38
|
+
b: 0,
|
|
39
|
+
c: 0,
|
|
40
|
+
d: 1,
|
|
41
|
+
};
|
|
42
|
+
context.setTransform(defaultTransform.a, defaultTransform.b, defaultTransform.c, defaultTransform.d, position.x, position.y);
|
|
32
43
|
const color = (0, engine_1.rangeColorToRgb)(stroke.color);
|
|
33
44
|
if (!color) {
|
|
34
45
|
return;
|
|
@@ -36,13 +47,13 @@
|
|
|
36
47
|
context.strokeStyle = (0, engine_1.getStyleFromRgb)(color, stroke.opacity);
|
|
37
48
|
context.lineWidth = stroke.width;
|
|
38
49
|
context.stroke(path);
|
|
39
|
-
context.
|
|
50
|
+
context.resetTransform();
|
|
40
51
|
}
|
|
41
52
|
exports.drawPolygonMaskPath = drawPolygonMaskPath;
|
|
42
53
|
function parsePaths(paths, scale, offset) {
|
|
43
|
-
const res = [];
|
|
54
|
+
const res = [], defaultCount = 0;
|
|
44
55
|
for (const path of paths) {
|
|
45
|
-
const segments = path.element.pathSegList, len = segments?.numberOfItems ??
|
|
56
|
+
const segments = path.element.pathSegList, len = segments?.numberOfItems ?? defaultCount, p = {
|
|
46
57
|
x: 0,
|
|
47
58
|
y: 0,
|
|
48
59
|
};
|
|
@@ -99,16 +110,16 @@
|
|
|
99
110
|
}
|
|
100
111
|
exports.parsePaths = parsePaths;
|
|
101
112
|
function calcClosestPtOnSegment(s1, s2, pos) {
|
|
102
|
-
const { dx: dx1, dy: dy1 } = (0, engine_1.getDistances)(pos, s1), { dx: dx2, dy: dy2 } = (0, engine_1.getDistances)(s2, s1), t = (dx1 * dx2 + dy1 * dy2) / (dx2 **
|
|
113
|
+
const { dx: dx1, dy: dy1 } = (0, engine_1.getDistances)(pos, s1), { dx: dx2, dy: dy2 } = (0, engine_1.getDistances)(s2, s1), t = (dx1 * dx2 + dy1 * dy2) / (dx2 ** squareExp + dy2 ** squareExp), res = {
|
|
103
114
|
x: s1.x + dx2 * t,
|
|
104
115
|
y: s1.y + dy2 * t,
|
|
105
|
-
isOnSegment: t >=
|
|
116
|
+
isOnSegment: t >= inSegmentRange.min && t <= inSegmentRange.max,
|
|
106
117
|
};
|
|
107
|
-
if (t <
|
|
118
|
+
if (t < inSegmentRange.min) {
|
|
108
119
|
res.x = s1.x;
|
|
109
120
|
res.y = s1.y;
|
|
110
121
|
}
|
|
111
|
-
else if (t >
|
|
122
|
+
else if (t > inSegmentRange.max) {
|
|
112
123
|
res.x = s2.x;
|
|
113
124
|
res.y = s2.y;
|
|
114
125
|
}
|
|
@@ -116,7 +127,7 @@
|
|
|
116
127
|
}
|
|
117
128
|
exports.calcClosestPtOnSegment = calcClosestPtOnSegment;
|
|
118
129
|
function segmentBounce(start, stop, velocity) {
|
|
119
|
-
const { dx, dy } = (0, engine_1.getDistances)(start, stop), wallAngle = Math.atan2(dy, dx), wallNormal = engine_1.Vector.create(Math.sin(wallAngle), -Math.cos(wallAngle)), d =
|
|
130
|
+
const { dx, dy } = (0, engine_1.getDistances)(start, stop), wallAngle = Math.atan2(dy, dx), wallNormal = engine_1.Vector.create(Math.sin(wallAngle), -Math.cos(wallAngle)), d = double * (velocity.x * wallNormal.x + velocity.y * wallNormal.y);
|
|
120
131
|
wallNormal.multTo(d);
|
|
121
132
|
velocity.subFrom(wallNormal);
|
|
122
133
|
}
|