@tsparticles/plugin-polygon-mask 3.0.0-alpha.0 → 3.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +15 -11
  2. package/browser/Options/Classes/PolygonMask.js +2 -8
  3. package/browser/Options/Classes/PolygonMaskDraw.js +1 -18
  4. package/browser/Options/Classes/PolygonMaskDrawStroke.js +3 -4
  5. package/browser/PolygonMaskInstance.js +297 -305
  6. package/browser/index.js +7 -8
  7. package/browser/pathseg.js +1 -1
  8. package/browser/utils.js +3 -5
  9. package/cjs/Options/Classes/PolygonMask.js +2 -8
  10. package/cjs/Options/Classes/PolygonMaskDraw.js +1 -18
  11. package/cjs/Options/Classes/PolygonMaskDrawStroke.js +2 -3
  12. package/cjs/PolygonMaskInstance.js +309 -332
  13. package/cjs/index.js +7 -19
  14. package/cjs/pathseg.js +1 -1
  15. package/cjs/utils.js +4 -6
  16. package/esm/Options/Classes/PolygonMask.js +2 -8
  17. package/esm/Options/Classes/PolygonMaskDraw.js +1 -18
  18. package/esm/Options/Classes/PolygonMaskDrawStroke.js +3 -4
  19. package/esm/PolygonMaskInstance.js +297 -305
  20. package/esm/index.js +7 -8
  21. package/esm/pathseg.js +1 -1
  22. package/esm/utils.js +3 -5
  23. package/package.json +8 -5
  24. package/report.html +4 -4
  25. package/tsparticles.plugin.polygon-mask.js +336 -362
  26. package/tsparticles.plugin.polygon-mask.min.js +1 -1
  27. package/tsparticles.plugin.polygon-mask.min.js.LICENSE.txt +1 -8
  28. package/types/Options/Classes/PolygonMask.d.ts +1 -4
  29. package/types/Options/Classes/PolygonMaskDraw.d.ts +1 -6
  30. package/types/Options/Classes/PolygonMaskDrawStroke.d.ts +1 -2
  31. package/types/Options/Interfaces/IPolygonMaskDraw.d.ts +0 -3
  32. package/types/PolygonMaskInstance.d.ts +13 -15
  33. package/types/index.d.ts +1 -1
  34. package/types/utils.d.ts +1 -2
  35. package/umd/Options/Classes/PolygonMask.js +3 -9
  36. package/umd/Options/Classes/PolygonMaskDraw.js +2 -19
  37. package/umd/Options/Classes/PolygonMaskDrawStroke.js +2 -3
  38. package/umd/PolygonMaskInstance.js +298 -306
  39. package/umd/index.js +7 -8
  40. package/umd/pathseg.js +1 -1
  41. package/umd/utils.js +3 -5
@@ -4,17 +4,300 @@
4
4
  if (v !== undefined) module.exports = v;
5
5
  }
6
6
  else if (typeof define === "function" && define.amd) {
7
- define(["require", "exports", "./utils", "@tsparticles/engine"], factory);
7
+ define(["require", "exports", "@tsparticles/engine", "./utils"], factory);
8
8
  }
9
9
  })(function (require, exports) {
10
10
  "use strict";
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.PolygonMaskInstance = void 0;
13
- const utils_1 = require("./utils");
14
13
  const engine_1 = require("@tsparticles/engine");
15
- const noPolygonDataLoaded = "No polygon data loaded.", noPolygonFound = "No polygon found, you need to specify SVG url in config.";
14
+ const utils_1 = require("./utils");
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.`;
16
16
  class PolygonMaskInstance {
17
17
  constructor(container, engine) {
18
+ this._checkInsidePolygon = (position) => {
19
+ const container = this._container, options = container.actualOptions.polygon;
20
+ if (!options?.enable || options.type === "none" || options.type === "inline") {
21
+ return true;
22
+ }
23
+ if (!this.raw) {
24
+ throw new Error(noPolygonFound);
25
+ }
26
+ const canvasSize = container.canvas.size, x = position?.x ?? (0, engine_1.getRandom)() * canvasSize.width, y = position?.y ?? (0, engine_1.getRandom)() * canvasSize.height;
27
+ let inside = false;
28
+ for (let i = 0, j = this.raw.length - 1; i < this.raw.length; j = i++) {
29
+ 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
+ if (intersect) {
31
+ inside = !inside;
32
+ }
33
+ }
34
+ return options.type === "inside"
35
+ ? inside
36
+ : options.type === "outside"
37
+ ? !inside
38
+ : false;
39
+ };
40
+ this._createPath2D = () => {
41
+ const container = this._container, options = container.actualOptions.polygon;
42
+ if (!options || !this.paths?.length) {
43
+ return;
44
+ }
45
+ for (const path of this.paths) {
46
+ const pathData = path.element?.getAttribute("d");
47
+ if (pathData) {
48
+ const path2d = new Path2D(pathData), matrix = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix(), finalPath = new Path2D(), transform = matrix.scale(this._scale);
49
+ if (finalPath.addPath) {
50
+ finalPath.addPath(path2d, transform);
51
+ path.path2d = finalPath;
52
+ }
53
+ else {
54
+ delete path.path2d;
55
+ }
56
+ }
57
+ else {
58
+ delete path.path2d;
59
+ }
60
+ if (path.path2d || !this.raw) {
61
+ continue;
62
+ }
63
+ path.path2d = new Path2D();
64
+ path.path2d.moveTo(this.raw[0].x, this.raw[0].y);
65
+ this.raw.forEach((pos, i) => {
66
+ if (i > 0) {
67
+ path.path2d?.lineTo(pos.x, pos.y);
68
+ }
69
+ });
70
+ path.path2d.closePath();
71
+ }
72
+ };
73
+ this._downloadSvgPath = async (svgUrl, force) => {
74
+ const options = this._container.actualOptions.polygon;
75
+ if (!options) {
76
+ return;
77
+ }
78
+ const url = svgUrl || options.url, forceDownload = force ?? false;
79
+ if (!url || (this.paths !== undefined && !forceDownload)) {
80
+ return this.raw;
81
+ }
82
+ const req = await fetch(url);
83
+ if (!req.ok) {
84
+ throw new Error(`${engine_1.errorPrefix} occurred during polygon mask download`);
85
+ }
86
+ return this._parseSvgPath(await req.text(), force);
87
+ };
88
+ this._drawPoints = () => {
89
+ if (!this.raw) {
90
+ return;
91
+ }
92
+ for (const item of this.raw) {
93
+ this._container.particles.addParticle({
94
+ x: item.x,
95
+ y: item.y,
96
+ });
97
+ }
98
+ };
99
+ this._getEquidistantPointByIndex = (index) => {
100
+ const container = this._container, options = container.actualOptions, polygonMaskOptions = options.polygon;
101
+ if (!polygonMaskOptions) {
102
+ return;
103
+ }
104
+ if (!this.raw || !this.raw.length || !this.paths?.length) {
105
+ throw new Error(noPolygonDataLoaded);
106
+ }
107
+ let offset = 0, point;
108
+ const totalLength = this.paths.reduce((tot, path) => tot + path.length, 0), distance = totalLength / options.particles.number.value;
109
+ for (const path of this.paths) {
110
+ const pathDistance = distance * index - offset;
111
+ if (pathDistance <= path.length) {
112
+ point = path.element.getPointAtLength(pathDistance);
113
+ break;
114
+ }
115
+ else {
116
+ offset += path.length;
117
+ }
118
+ }
119
+ const scale = this._scale;
120
+ return {
121
+ x: (point?.x ?? 0) * scale + (this.offset?.x ?? 0),
122
+ y: (point?.y ?? 0) * scale + (this.offset?.y ?? 0),
123
+ };
124
+ };
125
+ this._getPointByIndex = (index) => {
126
+ if (!this.raw || !this.raw.length) {
127
+ throw new Error(noPolygonDataLoaded);
128
+ }
129
+ const coords = this.raw[index % this.raw.length];
130
+ return {
131
+ x: coords.x,
132
+ y: coords.y,
133
+ };
134
+ };
135
+ this._getRandomPoint = () => {
136
+ if (!this.raw || !this.raw.length) {
137
+ throw new Error(noPolygonDataLoaded);
138
+ }
139
+ const coords = (0, engine_1.itemFromArray)(this.raw);
140
+ return {
141
+ x: coords.x,
142
+ y: coords.y,
143
+ };
144
+ };
145
+ this._getRandomPointByLength = () => {
146
+ const container = this._container, options = container.actualOptions.polygon;
147
+ if (!options) {
148
+ return;
149
+ }
150
+ if (!this.raw || !this.raw.length || !this.paths?.length) {
151
+ throw new Error(noPolygonDataLoaded);
152
+ }
153
+ const path = (0, engine_1.itemFromArray)(this.paths), distance = Math.floor((0, engine_1.getRandom)() * path.length) + 1, point = path.element.getPointAtLength(distance), scale = this._scale;
154
+ return {
155
+ x: point.x * scale + (this.offset?.x || 0),
156
+ y: point.y * scale + (this.offset?.y || 0),
157
+ };
158
+ };
159
+ this._initRawData = async (force) => {
160
+ const options = this._container.actualOptions.polygon;
161
+ if (!options) {
162
+ return;
163
+ }
164
+ if (options.url) {
165
+ this.raw = await this._downloadSvgPath(options.url, force);
166
+ }
167
+ else if (options.data) {
168
+ const data = options.data;
169
+ let svg;
170
+ if ((0, engine_1.isString)(data)) {
171
+ svg = data;
172
+ }
173
+ else {
174
+ const getPath = (p) => `<path d="${p}" />`, path = (0, engine_1.isArray)(data.path) ? data.path.map(getPath).join("") : getPath(data.path);
175
+ const namespaces = 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"';
176
+ svg = `<svg ${namespaces} width="${data.size.width}" height="${data.size.height}">${path}</svg>`;
177
+ }
178
+ this.raw = this._parseSvgPath(svg, force);
179
+ }
180
+ this._createPath2D();
181
+ this._engine.dispatchEvent("polygonMaskLoaded", {
182
+ container: this._container,
183
+ });
184
+ };
185
+ this._parseSvgPath = (xml, force) => {
186
+ const forceDownload = force ?? false;
187
+ if (this.paths !== undefined && !forceDownload) {
188
+ return this.raw;
189
+ }
190
+ const container = this._container, options = container.actualOptions.polygon;
191
+ if (!options) {
192
+ return;
193
+ }
194
+ const parser = new DOMParser(), doc = parser.parseFromString(xml, "image/svg+xml"), svg = doc.getElementsByTagName("svg")[0];
195
+ let svgPaths = svg.getElementsByTagName("path");
196
+ if (!svgPaths.length) {
197
+ svgPaths = doc.getElementsByTagName("path");
198
+ }
199
+ this.paths = [];
200
+ for (let i = 0; i < svgPaths.length; i++) {
201
+ const path = svgPaths.item(i);
202
+ if (path) {
203
+ this.paths.push({
204
+ element: path,
205
+ length: path.getTotalLength(),
206
+ });
207
+ }
208
+ }
209
+ const scale = this._scale;
210
+ this.dimension.width = parseFloat(svg.getAttribute("width") ?? "0") * scale;
211
+ this.dimension.height = parseFloat(svg.getAttribute("height") ?? "0") * scale;
212
+ const position = options.position ?? {
213
+ x: 50,
214
+ y: 50,
215
+ }, canvasSize = container.canvas.size;
216
+ this.offset = {
217
+ x: (canvasSize.width * position.x) / 100 - this.dimension.width / 2,
218
+ y: (canvasSize.height * position.y) / 100 - this.dimension.height / 2,
219
+ };
220
+ return (0, utils_1.parsePaths)(this.paths, scale, this.offset);
221
+ };
222
+ this._polygonBounce = (particle, _delta, direction) => {
223
+ const options = this._container.actualOptions.polygon;
224
+ if (!this.raw || !options?.enable || direction !== "top") {
225
+ return false;
226
+ }
227
+ if (options.type === "inside" || options.type === "outside") {
228
+ let closest, dx, dy;
229
+ const pos = particle.getPosition(), radius = particle.getRadius();
230
+ for (let i = 0, j = this.raw.length - 1; i < this.raw.length; j = i++) {
231
+ const pi = this.raw[i], pj = this.raw[j];
232
+ closest = (0, utils_1.calcClosestPtOnSegment)(pi, pj, pos);
233
+ const dist = (0, engine_1.getDistances)(pos, closest);
234
+ [dx, dy] = [dist.dx, dist.dy];
235
+ if (dist.distance < radius) {
236
+ (0, utils_1.segmentBounce)(pi, pj, particle.velocity);
237
+ return true;
238
+ }
239
+ }
240
+ if (closest && dx !== undefined && dy !== undefined && !this._checkInsidePolygon(pos)) {
241
+ const factor = { x: 1, y: 1 }, diameter = radius * 2;
242
+ if (pos.x >= closest.x) {
243
+ factor.x = -1;
244
+ }
245
+ if (pos.y >= closest.y) {
246
+ factor.y = -1;
247
+ }
248
+ particle.position.x = closest.x + diameter * factor.x;
249
+ particle.position.y = closest.y + diameter * factor.y;
250
+ particle.velocity.mult(-1);
251
+ return true;
252
+ }
253
+ }
254
+ else if (options.type === "inline" && particle.initialPosition) {
255
+ const dist = (0, engine_1.getDistance)(particle.initialPosition, particle.getPosition()), { velocity } = particle;
256
+ if (dist > this._moveRadius) {
257
+ velocity.x = velocity.y / 2 - velocity.x;
258
+ velocity.y = velocity.x / 2 - velocity.y;
259
+ return true;
260
+ }
261
+ }
262
+ return false;
263
+ };
264
+ this._randomPoint = () => {
265
+ const container = this._container, options = container.actualOptions.polygon;
266
+ if (!options) {
267
+ return;
268
+ }
269
+ let position;
270
+ if (options.type === "inline") {
271
+ switch (options.inline.arrangement) {
272
+ case "random-point":
273
+ position = this._getRandomPoint();
274
+ break;
275
+ case "random-length":
276
+ position = this._getRandomPointByLength();
277
+ break;
278
+ case "equidistant":
279
+ position = this._getEquidistantPointByIndex(container.particles.count);
280
+ break;
281
+ case "one-per-point":
282
+ case "per-point":
283
+ default:
284
+ position = this._getPointByIndex(container.particles.count);
285
+ }
286
+ }
287
+ else {
288
+ const canvasSize = container.canvas.size;
289
+ position = {
290
+ x: (0, engine_1.getRandom)() * canvasSize.width,
291
+ y: (0, engine_1.getRandom)() * canvasSize.height,
292
+ };
293
+ }
294
+ if (this._checkInsidePolygon(position)) {
295
+ return position;
296
+ }
297
+ else {
298
+ return this._randomPoint();
299
+ }
300
+ };
18
301
  this._container = container;
19
302
  this._engine = engine;
20
303
  this.dimension = {
@@ -26,18 +309,17 @@
26
309
  }
27
310
  clickPositionValid(position) {
28
311
  const options = this._container.actualOptions.polygon;
29
- return (!!(options === null || options === void 0 ? void 0 : options.enable) &&
312
+ return (!!options?.enable &&
30
313
  options.type !== "none" &&
31
314
  options.type !== "inline" &&
32
- this.checkInsidePolygon(position));
315
+ this._checkInsidePolygon(position));
33
316
  }
34
317
  draw(context) {
35
- var _a;
36
- if (!((_a = this.paths) === null || _a === void 0 ? void 0 : _a.length)) {
318
+ if (!this.paths?.length) {
37
319
  return;
38
320
  }
39
321
  const options = this._container.actualOptions.polygon;
40
- if (!(options === null || options === void 0 ? void 0 : options.enable)) {
322
+ if (!options?.enable) {
41
323
  return;
42
324
  }
43
325
  const polygonDraw = options.draw;
@@ -66,41 +348,40 @@
66
348
  this._moveRadius = polygonMaskOptions.move.radius * pxRatio;
67
349
  this._scale = polygonMaskOptions.scale * pxRatio;
68
350
  if (polygonMaskOptions.enable) {
69
- await this.initRawData();
351
+ await this._initRawData();
70
352
  }
71
353
  }
72
354
  particleBounce(particle, delta, direction) {
73
- return this.polygonBounce(particle, delta, direction);
355
+ return this._polygonBounce(particle, delta, direction);
74
356
  }
75
357
  particlePosition(position) {
76
- var _a, _b;
77
358
  const options = this._container.actualOptions.polygon;
78
- if (!((options === null || options === void 0 ? void 0 : options.enable) && ((_b = (_a = this.raw) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0)) {
359
+ if (!(options?.enable && (this.raw?.length ?? 0) > 0)) {
79
360
  return;
80
361
  }
81
- return (0, engine_1.deepExtend)({}, position ? position : this.randomPoint());
362
+ return (0, engine_1.deepExtend)({}, position ? position : this._randomPoint());
82
363
  }
83
364
  particlesInitialization() {
84
365
  const options = this._container.actualOptions.polygon;
85
- if ((options === null || options === void 0 ? void 0 : options.enable) &&
366
+ if (options?.enable &&
86
367
  options.type === "inline" &&
87
368
  (options.inline.arrangement === "one-per-point" ||
88
369
  options.inline.arrangement === "per-point")) {
89
- this.drawPoints();
370
+ this._drawPoints();
90
371
  return true;
91
372
  }
92
373
  return false;
93
374
  }
94
375
  resize() {
95
376
  const container = this._container, options = container.actualOptions.polygon;
96
- if (!((options === null || options === void 0 ? void 0 : options.enable) && options.type !== "none")) {
377
+ if (!(options?.enable && options.type !== "none")) {
97
378
  return;
98
379
  }
99
380
  if (this.redrawTimeout) {
100
381
  clearTimeout(this.redrawTimeout);
101
382
  }
102
383
  this.redrawTimeout = window.setTimeout(async () => {
103
- await this.initRawData(true);
384
+ await this._initRawData(true);
104
385
  await container.particles.redraw();
105
386
  }, 250);
106
387
  }
@@ -108,295 +389,6 @@
108
389
  delete this.raw;
109
390
  delete this.paths;
110
391
  }
111
- checkInsidePolygon(position) {
112
- var _a, _b;
113
- const container = this._container, options = container.actualOptions.polygon;
114
- if (!(options === null || options === void 0 ? void 0 : options.enable) || options.type === "none" || options.type === "inline") {
115
- return true;
116
- }
117
- if (!this.raw) {
118
- throw new Error(noPolygonFound);
119
- }
120
- const canvasSize = container.canvas.size, x = (_a = position === null || position === void 0 ? void 0 : position.x) !== null && _a !== void 0 ? _a : (0, engine_1.getRandom)() * canvasSize.width, y = (_b = position === null || position === void 0 ? void 0 : position.y) !== null && _b !== void 0 ? _b : (0, engine_1.getRandom)() * canvasSize.height;
121
- let inside = false;
122
- for (let i = 0, j = this.raw.length - 1; i < this.raw.length; j = i++) {
123
- 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;
124
- if (intersect) {
125
- inside = !inside;
126
- }
127
- }
128
- return options.type === "inside"
129
- ? inside
130
- : options.type === "outside"
131
- ? !inside
132
- : false;
133
- }
134
- createPath2D() {
135
- var _a, _b;
136
- const container = this._container, options = container.actualOptions.polygon;
137
- if (!options || !((_a = this.paths) === null || _a === void 0 ? void 0 : _a.length)) {
138
- return;
139
- }
140
- for (const path of this.paths) {
141
- const pathData = (_b = path.element) === null || _b === void 0 ? void 0 : _b.getAttribute("d");
142
- if (pathData) {
143
- const path2d = new Path2D(pathData), matrix = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix(), finalPath = new Path2D(), transform = matrix.scale(this._scale);
144
- if (finalPath.addPath) {
145
- finalPath.addPath(path2d, transform);
146
- path.path2d = finalPath;
147
- }
148
- else {
149
- delete path.path2d;
150
- }
151
- }
152
- else {
153
- delete path.path2d;
154
- }
155
- if (path.path2d || !this.raw) {
156
- continue;
157
- }
158
- path.path2d = new Path2D();
159
- path.path2d.moveTo(this.raw[0].x, this.raw[0].y);
160
- this.raw.forEach((pos, i) => {
161
- var _a;
162
- if (i > 0) {
163
- (_a = path.path2d) === null || _a === void 0 ? void 0 : _a.lineTo(pos.x, pos.y);
164
- }
165
- });
166
- path.path2d.closePath();
167
- }
168
- }
169
- async downloadSvgPath(svgUrl, force) {
170
- const options = this._container.actualOptions.polygon;
171
- if (!options) {
172
- return;
173
- }
174
- const url = svgUrl || options.url, forceDownload = force !== null && force !== void 0 ? force : false;
175
- if (!url || (this.paths !== undefined && !forceDownload)) {
176
- return this.raw;
177
- }
178
- const req = await fetch(url);
179
- if (!req.ok) {
180
- throw new Error("tsParticles Error - Error occurred during polygon mask download");
181
- }
182
- return this.parseSvgPath(await req.text(), force);
183
- }
184
- drawPoints() {
185
- if (!this.raw) {
186
- return;
187
- }
188
- for (const item of this.raw) {
189
- this._container.particles.addParticle({
190
- x: item.x,
191
- y: item.y,
192
- });
193
- }
194
- }
195
- getEquidistantPointByIndex(index) {
196
- var _a, _b, _c, _d, _e, _f, _g;
197
- const container = this._container, options = container.actualOptions, polygonMaskOptions = options.polygon;
198
- if (!polygonMaskOptions) {
199
- return;
200
- }
201
- if (!this.raw || !this.raw.length || !((_a = this.paths) === null || _a === void 0 ? void 0 : _a.length))
202
- throw new Error(noPolygonDataLoaded);
203
- let offset = 0, point;
204
- const totalLength = this.paths.reduce((tot, path) => tot + path.length, 0), distance = totalLength / options.particles.number.value;
205
- for (const path of this.paths) {
206
- const pathDistance = distance * index - offset;
207
- if (pathDistance <= path.length) {
208
- point = path.element.getPointAtLength(pathDistance);
209
- break;
210
- }
211
- else {
212
- offset += path.length;
213
- }
214
- }
215
- const scale = this._scale;
216
- return {
217
- x: ((_b = point === null || point === void 0 ? void 0 : point.x) !== null && _b !== void 0 ? _b : 0) * scale + ((_d = (_c = this.offset) === null || _c === void 0 ? void 0 : _c.x) !== null && _d !== void 0 ? _d : 0),
218
- y: ((_e = point === null || point === void 0 ? void 0 : point.y) !== null && _e !== void 0 ? _e : 0) * scale + ((_g = (_f = this.offset) === null || _f === void 0 ? void 0 : _f.y) !== null && _g !== void 0 ? _g : 0),
219
- };
220
- }
221
- getPointByIndex(index) {
222
- if (!this.raw || !this.raw.length) {
223
- throw new Error(noPolygonDataLoaded);
224
- }
225
- const coords = this.raw[index % this.raw.length];
226
- return {
227
- x: coords.x,
228
- y: coords.y,
229
- };
230
- }
231
- getRandomPoint() {
232
- if (!this.raw || !this.raw.length) {
233
- throw new Error(noPolygonDataLoaded);
234
- }
235
- const coords = (0, engine_1.itemFromArray)(this.raw);
236
- return {
237
- x: coords.x,
238
- y: coords.y,
239
- };
240
- }
241
- getRandomPointByLength() {
242
- var _a, _b, _c;
243
- const container = this._container, options = container.actualOptions.polygon;
244
- if (!options) {
245
- return;
246
- }
247
- if (!this.raw || !this.raw.length || !((_a = this.paths) === null || _a === void 0 ? void 0 : _a.length)) {
248
- throw new Error(noPolygonDataLoaded);
249
- }
250
- const path = (0, engine_1.itemFromArray)(this.paths), distance = Math.floor((0, engine_1.getRandom)() * path.length) + 1, point = path.element.getPointAtLength(distance), scale = this._scale;
251
- return {
252
- x: point.x * scale + (((_b = this.offset) === null || _b === void 0 ? void 0 : _b.x) || 0),
253
- y: point.y * scale + (((_c = this.offset) === null || _c === void 0 ? void 0 : _c.y) || 0),
254
- };
255
- }
256
- async initRawData(force) {
257
- const options = this._container.actualOptions.polygon;
258
- if (!options) {
259
- return;
260
- }
261
- if (options.url) {
262
- this.raw = await this.downloadSvgPath(options.url, force);
263
- }
264
- else if (options.data) {
265
- const data = options.data;
266
- let svg;
267
- if (typeof data !== "string") {
268
- const path = data.path instanceof Array
269
- ? data.path.map((t) => `<path d="${t}" />`).join("")
270
- : `<path d="${data.path}" />`;
271
- const namespaces = 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"';
272
- svg = `<svg ${namespaces} width="${data.size.width}" height="${data.size.height}">${path}</svg>`;
273
- }
274
- else {
275
- svg = data;
276
- }
277
- this.raw = this.parseSvgPath(svg, force);
278
- }
279
- this.createPath2D();
280
- this._engine.dispatchEvent("polygonMaskLoaded", {
281
- container: this._container,
282
- });
283
- }
284
- parseSvgPath(xml, force) {
285
- var _a, _b, _c;
286
- const forceDownload = force !== null && force !== void 0 ? force : false;
287
- if (this.paths !== undefined && !forceDownload) {
288
- return this.raw;
289
- }
290
- const container = this._container, options = container.actualOptions.polygon;
291
- if (!options) {
292
- return;
293
- }
294
- const parser = new DOMParser(), doc = parser.parseFromString(xml, "image/svg+xml"), svg = doc.getElementsByTagName("svg")[0];
295
- let svgPaths = svg.getElementsByTagName("path");
296
- if (!svgPaths.length) {
297
- svgPaths = doc.getElementsByTagName("path");
298
- }
299
- this.paths = [];
300
- for (let i = 0; i < svgPaths.length; i++) {
301
- const path = svgPaths.item(i);
302
- if (path) {
303
- this.paths.push({
304
- element: path,
305
- length: path.getTotalLength(),
306
- });
307
- }
308
- }
309
- const scale = this._scale;
310
- this.dimension.width = parseFloat((_a = svg.getAttribute("width")) !== null && _a !== void 0 ? _a : "0") * scale;
311
- this.dimension.height = parseFloat((_b = svg.getAttribute("height")) !== null && _b !== void 0 ? _b : "0") * scale;
312
- const position = (_c = options.position) !== null && _c !== void 0 ? _c : {
313
- x: 50,
314
- y: 50,
315
- };
316
- this.offset = {
317
- x: (container.canvas.size.width * position.x) / 100 - this.dimension.width / 2,
318
- y: (container.canvas.size.height * position.y) / 100 - this.dimension.height / 2,
319
- };
320
- return (0, utils_1.parsePaths)(this.paths, scale, this.offset);
321
- }
322
- polygonBounce(particle, _delta, direction) {
323
- const options = this._container.actualOptions.polygon;
324
- if (!this.raw || !(options === null || options === void 0 ? void 0 : options.enable) || direction !== "top") {
325
- return false;
326
- }
327
- if (options.type === "inside" || options.type === "outside") {
328
- let closest, dx, dy;
329
- const pos = particle.getPosition(), radius = particle.getRadius();
330
- for (let i = 0, j = this.raw.length - 1; i < this.raw.length; j = i++) {
331
- const pi = this.raw[i], pj = this.raw[j];
332
- closest = (0, utils_1.calcClosestPtOnSegment)(pi, pj, pos);
333
- const dist = (0, engine_1.getDistances)(pos, closest);
334
- [dx, dy] = [dist.dx, dist.dy];
335
- if (dist.distance < radius) {
336
- (0, utils_1.segmentBounce)(pi, pj, particle.velocity);
337
- return true;
338
- }
339
- }
340
- if (closest && dx !== undefined && dy !== undefined && !this.checkInsidePolygon(pos)) {
341
- const factor = { x: 1, y: 1 };
342
- if (particle.position.x >= closest.x) {
343
- factor.x = -1;
344
- }
345
- if (particle.position.y >= closest.y) {
346
- factor.y = -1;
347
- }
348
- particle.position.x = closest.x + radius * 2 * factor.x;
349
- particle.position.y = closest.y + radius * 2 * factor.y;
350
- particle.velocity.mult(-1);
351
- return true;
352
- }
353
- }
354
- else if (options.type === "inline" && particle.initialPosition) {
355
- const dist = (0, engine_1.getDistance)(particle.initialPosition, particle.getPosition());
356
- if (dist > this._moveRadius) {
357
- particle.velocity.x = particle.velocity.y / 2 - particle.velocity.x;
358
- particle.velocity.y = particle.velocity.x / 2 - particle.velocity.y;
359
- return true;
360
- }
361
- }
362
- return false;
363
- }
364
- randomPoint() {
365
- const container = this._container, options = container.actualOptions.polygon;
366
- if (!options) {
367
- return;
368
- }
369
- let position;
370
- if (options.type === "inline") {
371
- switch (options.inline.arrangement) {
372
- case "random-point":
373
- position = this.getRandomPoint();
374
- break;
375
- case "random-length":
376
- position = this.getRandomPointByLength();
377
- break;
378
- case "equidistant":
379
- position = this.getEquidistantPointByIndex(container.particles.count);
380
- break;
381
- case "one-per-point":
382
- case "per-point":
383
- default:
384
- position = this.getPointByIndex(container.particles.count);
385
- }
386
- }
387
- else {
388
- position = {
389
- x: (0, engine_1.getRandom)() * container.canvas.size.width,
390
- y: (0, engine_1.getRandom)() * container.canvas.size.height,
391
- };
392
- }
393
- if (this.checkInsidePolygon(position)) {
394
- return position;
395
- }
396
- else {
397
- return this.randomPoint();
398
- }
399
- }
400
392
  }
401
393
  exports.PolygonMaskInstance = PolygonMaskInstance;
402
394
  });