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