@tsparticles/plugin-polygon-mask 3.1.0 → 3.2.1
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/719.min.js +2 -0
- package/719.min.js.LICENSE.txt +1 -0
- package/787.min.js +2 -0
- package/787.min.js.LICENSE.txt +1 -0
- package/856.min.js +2 -0
- package/856.min.js.LICENSE.txt +1 -0
- package/browser/PolygonMaskInstance.js +14 -11
- package/browser/PolygonMaskPlugin.js +25 -0
- package/browser/index.js +1 -25
- package/browser/utils.js +1 -1
- package/cjs/PolygonMaskInstance.js +41 -15
- package/cjs/PolygonMaskPlugin.js +52 -0
- package/cjs/index.js +13 -25
- package/cjs/utils.js +3 -3
- package/dist_browser_PolygonMaskInstance_js.js +30 -0
- package/dist_browser_PolygonMaskPlugin_js.js +90 -0
- package/dist_browser_utils_js.js +30 -0
- package/esm/PolygonMaskInstance.js +14 -11
- package/esm/PolygonMaskPlugin.js +25 -0
- package/esm/index.js +1 -25
- package/esm/utils.js +1 -1
- package/package.json +2 -2
- package/report.html +3 -3
- package/tsparticles.plugin.polygon-mask.js +244 -2195
- package/tsparticles.plugin.polygon-mask.min.js +1 -1
- package/tsparticles.plugin.polygon-mask.min.js.LICENSE.txt +1 -1
- package/types/PolygonMaskInstance.d.ts +2 -2
- package/types/PolygonMaskPlugin.d.ts +11 -0
- package/types/utils.d.ts +1 -1
- package/umd/PolygonMaskInstance.js +43 -16
- package/umd/PolygonMaskPlugin.js +63 -0
- package/umd/index.js +15 -26
- package/umd/utils.js +3 -3
package/719.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 719.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_plugin_polygon_mask=this.webpackChunk_tsparticles_plugin_polygon_mask||[]).push([[719],{719:(t,i,e)=>{e.d(i,{PolygonMaskInstance:()=>c});var n=e(533);const s=`${n.errorPrefix} No polygon data loaded.`,a=`${n.errorPrefix} No polygon found, you need to specify SVG url in config.`,o=0,h=0,r=.5;class c{constructor(t,i){this._checkInsidePolygon=t=>{const i=this._container,e=i.actualOptions.polygon;if(!e?.enable||"none"===e.type||"inline"===e.type)return!0;if(!this.raw)throw new Error(a);const s=i.canvas.size,o=t?.x??(0,n.getRandom)()*s.width,h=t?.y??(0,n.getRandom)()*s.height;let r=!1;for(let t=0,i=this.raw.length-1;t<this.raw.length;i=t++){const e=this.raw[t],n=this.raw[i];e.y>h!=n.y>h&&o<(n.x-e.x)*(h-e.y)/(n.y-e.y)+e.x&&(r=!r)}return"inside"===e.type?r:"outside"===e.type&&!r},this._createPath2D=()=>{if(this._container.actualOptions.polygon&&this.paths?.length)for(const t of this.paths){const i=t.element?.getAttribute("d");if(i){const e=new Path2D(i),n=document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGMatrix(),s=new Path2D,a=n.scale(this._scale);s.addPath?(s.addPath(e,a),t.path2d=s):delete t.path2d}else delete t.path2d;if(t.path2d??!this.raw)continue;t.path2d=new Path2D;const e=0,n=this.raw[e];t.path2d.moveTo(n.x,n.y),this.raw.forEach(((i,n)=>{n>e&&t.path2d?.lineTo(i.x,i.y)})),t.path2d.closePath()}},this._downloadSvgPath=async(t,i)=>{const e=this._container.actualOptions.polygon;if(!e)return;const s=t??e.url,a=i??!1;if(!s||void 0!==this.paths&&!a)return this.raw;const o=await fetch(s);if(!o.ok)throw new Error(`${n.errorPrefix} occurred during polygon mask download`);return await this._parseSvgPath(await o.text(),i)},this._drawPoints=()=>{if(this.raw)for(const t of this.raw)this._container.particles.addParticle({x:t.x,y:t.y})},this._getEquidistantPointByIndex=t=>{const i=this._container.actualOptions;if(!i.polygon)return;if(!this.raw?.length||!this.paths?.length)throw new Error(s);let e,n=0;const a=this.paths.reduce(((t,i)=>t+i.length),0)/i.particles.number.value;for(const i of this.paths){const s=a*t-n;if(s<=i.length){e=i.element.getPointAtLength(s);break}n+=i.length}const r=this._scale;return{x:(e?.x??o)*r+(this.offset?.x??o),y:(e?.y??h)*r+(this.offset?.y??h)}},this._getPointByIndex=t=>{if(!this.raw?.length)throw new Error(s);const i=this.raw[t%this.raw.length];return{x:i.x,y:i.y}},this._getRandomPoint=()=>{if(!this.raw?.length)throw new Error(s);const t=(0,n.itemFromArray)(this.raw);return{x:t.x,y:t.y}},this._getRandomPointByLength=()=>{if(!this._container.actualOptions.polygon)return;if(!this.raw?.length||!this.paths?.length)throw new Error(s);const t=(0,n.itemFromArray)(this.paths),i=Math.floor((0,n.getRandom)()*t.length)+1,e=t.element.getPointAtLength(i),a=this._scale;return{x:e.x*a+(this.offset?.x??o),y:e.y*a+(this.offset?.y??h)}},this._initRawData=async t=>{const i=this._container.actualOptions.polygon;if(i){if(i.url)this.raw=await this._downloadSvgPath(i.url,t);else if(i.data){const e=i.data;let s;if((0,n.isString)(e))s=e;else{const t=t=>`<path d="${t}" />`,i=(0,n.isArray)(e.path)?e.path.map(t).join(""):t(e.path);s=`<svg ${'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"'} width="${e.size.width}" height="${e.size.height}">${i}</svg>`}this.raw=await this._parseSvgPath(s,t)}this._createPath2D(),this._engine.dispatchEvent("polygonMaskLoaded",{container:this._container})}},this._parseSvgPath=async(t,i)=>{const s=i??!1;if(void 0!==this.paths&&!s)return this.raw;const a=this._container,o=a.actualOptions.polygon;if(!o)return;const h=(new DOMParser).parseFromString(t,"image/svg+xml"),c=h.getElementsByTagName("svg")[0];let l=c.getElementsByTagName("path");l.length||(l=h.getElementsByTagName("path")),this.paths=[];for(let t=0;t<l.length;t++){const i=l.item(t);i&&this.paths.push({element:i,length:i.getTotalLength()})}const g=this._scale;this.dimension.width=parseFloat(c.getAttribute("width")??"0")*g,this.dimension.height=parseFloat(c.getAttribute("height")??"0")*g;const p=o.position??{x:50,y:50},d=a.canvas.size;this.offset={x:d.width*p.x/n.percentDenominator-this.dimension.width*r,y:d.height*p.y/n.percentDenominator-this.dimension.height*r};const{parsePaths:y}=await e.e(856).then(e.bind(e,856));return y(this.paths,g,this.offset)},this._polygonBounce=async(t,i,s)=>{const a=this._container.actualOptions.polygon;if(!this.raw||!a?.enable||"top"!==s)return!1;if("inside"===a.type||"outside"===a.type){let i,s,a;const o=t.getPosition(),h=t.getRadius(),r=1;for(let c=0,l=this.raw.length-r;c<this.raw.length;l=c++){const r=this.raw[c],g=this.raw[l],{calcClosestPointOnSegment:p}=await e.e(856).then(e.bind(e,856));i=p(r,g,o);const d=(0,n.getDistances)(o,i);if([s,a]=[d.dx,d.dy],d.distance<h){const{segmentBounce:i}=await e.e(856).then(e.bind(e,856));return i(r,g,t.velocity),!0}}if(i&&void 0!==s&&void 0!==a&&!this._checkInsidePolygon(o)){const e={x:1,y:1},n=2*h,s=-1;return o.x>=i.x&&(e.x=-1),o.y>=i.y&&(e.y=-1),t.position.x=i.x+n*e.x,t.position.y=i.y+n*e.y,t.velocity.mult(s),!0}}else if("inline"===a.type&&t.initialPosition){const i=(0,n.getDistance)(t.initialPosition,t.getPosition()),{velocity:e}=t;if(i>this._moveRadius)return e.x=e.y*r-e.x,e.y=e.x*r-e.y,!0}return!1},this._randomPoint=()=>{const t=this._container,i=t.actualOptions.polygon;if(!i)return;let e;if("inline"===i.type)switch(i.inline.arrangement){case"random-point":e=this._getRandomPoint();break;case"random-length":e=this._getRandomPointByLength();break;case"equidistant":e=this._getEquidistantPointByIndex(t.particles.count);break;default:e=this._getPointByIndex(t.particles.count)}else{const i=t.canvas.size;e={x:(0,n.getRandom)()*i.width,y:(0,n.getRandom)()*i.height}}return this._checkInsidePolygon(e)?e:this._randomPoint()},this._container=t,this._engine=i,this.dimension={height:0,width:0},this._moveRadius=0,this._scale=1}clickPositionValid(t){const i=this._container.actualOptions.polygon;return!!i?.enable&&"none"!==i.type&&"inline"!==i.type&&this._checkInsidePolygon(t)}async draw(t){if(!this.paths?.length)return;const i=this._container.actualOptions.polygon;if(!i?.enable)return;const n=i.draw;if(!n.enable)return;const s=this.raw;for(const i of this.paths){const a=i.path2d;if(t)if(a&&this.offset){const{drawPolygonMaskPath:i}=await e.e(856).then(e.bind(e,856));i(t,a,n.stroke,this.offset)}else if(s){const{drawPolygonMask:i}=await e.e(856).then(e.bind(e,856));i(t,s,n.stroke)}}}async init(){const t=this._container,i=t.actualOptions.polygon,e=t.retina.pixelRatio;i&&(this._moveRadius=i.move.radius*e,this._scale=i.scale*e,i.enable&&await this._initRawData())}async particleBounce(t,i,e){return await this._polygonBounce(t,i,e)}particlePosition(t){const i=this._container.actualOptions.polygon;if(i?.enable&&(this.raw?.length??0)>0)return(0,n.deepExtend)({},t||this._randomPoint())}particlesInitialization(){const t=this._container.actualOptions.polygon;return!(!t?.enable||"inline"!==t.type||"one-per-point"!==t.inline.arrangement&&"per-point"!==t.inline.arrangement)&&(this._drawPoints(),!0)}resize(){const t=this._container,i=t.actualOptions.polygon;if(!i?.enable||"none"===i.type)return;this.redrawTimeout&&clearTimeout(this.redrawTimeout);this.redrawTimeout=window.setTimeout((()=>{(async()=>{await this._initRawData(!0),await t.particles.redraw()})()}),250)}stop(){delete this.raw,delete this.paths}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Polygon Mask Plugin v3.2.1 by Matteo Bruni */
|
package/787.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 787.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_plugin_polygon_mask=this.webpackChunk_tsparticles_plugin_polygon_mask||[]).push([[787],{787:(t,i,s)=>{s.d(i,{PolygonMaskPlugin:()=>r});var o=s(533);class e{constructor(){this.color=new o.OptionsColor,this.width=.5,this.opacity=1}load(t){t&&(this.color=o.OptionsColor.create(this.color,t.color),(0,o.isString)(this.color.value)&&(this.opacity=(0,o.stringToAlpha)(this.color.value)??this.opacity),void 0!==t.opacity&&(this.opacity=t.opacity),void 0!==t.width&&(this.width=t.width))}}class n{constructor(){this.enable=!1,this.stroke=new e}load(t){if(!t)return;void 0!==t.enable&&(this.enable=t.enable);const i=t.stroke;this.stroke.load(i)}}class a{constructor(){this.arrangement="one-per-point"}load(t){t&&void 0!==t.arrangement&&(this.arrangement=t.arrangement)}}class h{constructor(){this.path=[],this.size={height:0,width:0}}load(t){t&&(void 0!==t.path&&(this.path=t.path),void 0!==t.size&&(void 0!==t.size.width&&(this.size.width=t.size.width),void 0!==t.size.height&&(this.size.height=t.size.height)))}}class l{constructor(){this.radius=10,this.type="path"}load(t){t&&(void 0!==t.radius&&(this.radius=t.radius),void 0!==t.type&&(this.type=t.type))}}class d{constructor(){this.draw=new n,this.enable=!1,this.inline=new a,this.move=new l,this.scale=1,this.type="none"}load(t){t&&(this.draw.load(t.draw),this.inline.load(t.inline),this.move.load(t.move),void 0!==t.scale&&(this.scale=t.scale),void 0!==t.type&&(this.type=t.type),void 0!==t.enable?this.enable=t.enable:this.enable="none"!==this.type,void 0!==t.url&&(this.url=t.url),void 0!==t.data&&((0,o.isString)(t.data)?this.data=t.data:(this.data=new h,this.data.load(t.data))),void 0!==t.position&&(this.position=(0,o.deepExtend)({},t.position)))}}class r{constructor(t){this.id="polygonMask",this._engine=t}async getPlugin(t){const{PolygonMaskInstance:i}=await s.e(719).then(s.bind(s,719));return new i(t,this._engine)}loadOptions(t,i){if(!this.needsPlugin(t)&&!this.needsPlugin(i))return;let s=t.polygon;void 0===s?.load&&(t.polygon=s=new d),s.load(i?.polygon)}needsPlugin(t){return t?.polygon?.enable??(void 0!==t?.polygon?.type&&"none"!==t.polygon.type)}}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Polygon Mask Plugin v3.2.1 by Matteo Bruni */
|
package/856.min.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! For license information please see 856.min.js.LICENSE.txt */
|
|
2
|
+
(this.webpackChunk_tsparticles_plugin_polygon_mask=this.webpackChunk_tsparticles_plugin_polygon_mask||[]).push([[856],{856:(e,t,s)=>{s.d(t,{calcClosestPointOnSegment:()=>A,drawPolygonMask:()=>c,drawPolygonMaskPath:()=>T,parsePaths:()=>E,segmentBounce:()=>S});var o=s(533);const a=2,n={min:0,max:1},_=2;function c(e,t,s){const a=(0,o.rangeColorToRgb)(s.color);if(!a)return;const n=t[0];e.beginPath(),e.moveTo(n.x,n.y);for(const s of t)e.lineTo(s.x,s.y);e.closePath(),e.strokeStyle=(0,o.getStyleFromRgb)(a),e.lineWidth=s.width,e.stroke()}function T(e,t,s,a){const n=1,_=0,c=0,T=1;e.setTransform(n,_,c,T,a.x,a.y);const E=(0,o.rangeColorToRgb)(s.color);E&&(e.strokeStyle=(0,o.getStyleFromRgb)(E,s.opacity),e.lineWidth=s.width,e.stroke(t),e.resetTransform())}function E(e,t,s){const o=[];for(const a of e){const e=a.element.pathSegList,n=e?.numberOfItems??0,_={x:0,y:0};for(let a=0;a<n;a++){const n=e?.getItem(a),c=window.SVGPathSeg;switch(n?.pathSegType){case c.PATHSEG_MOVETO_ABS:case c.PATHSEG_LINETO_ABS:case c.PATHSEG_CURVETO_CUBIC_ABS:case c.PATHSEG_CURVETO_QUADRATIC_ABS:case c.PATHSEG_ARC_ABS:case c.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:case c.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:{const e=n;_.x=e.x,_.y=e.y;break}case c.PATHSEG_LINETO_HORIZONTAL_ABS:_.x=n.x;break;case c.PATHSEG_LINETO_VERTICAL_ABS:_.y=n.y;break;case c.PATHSEG_LINETO_REL:case c.PATHSEG_MOVETO_REL:case c.PATHSEG_CURVETO_CUBIC_REL:case c.PATHSEG_CURVETO_QUADRATIC_REL:case c.PATHSEG_ARC_REL:case c.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:case c.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:{const e=n;_.x+=e.x,_.y+=e.y;break}case c.PATHSEG_LINETO_HORIZONTAL_REL:_.x+=n.x;break;case c.PATHSEG_LINETO_VERTICAL_REL:_.y+=n.y;break;case c.PATHSEG_UNKNOWN:case c.PATHSEG_CLOSEPATH:continue}o.push({x:_.x*t+s.x,y:_.y*t+s.y})}}return o}function A(e,t,s){const{dx:_,dy:c}=(0,o.getDistances)(s,e),{dx:T,dy:E}=(0,o.getDistances)(t,e),A=(_*T+c*E)/(T**a+E**a),S={x:e.x+T*A,y:e.y+E*A,isOnSegment:A>=n.min&&A<=n.max};return A<n.min?(S.x=e.x,S.y=e.y):A>n.max&&(S.x=t.x,S.y=t.y),S}function S(e,t,s){const{dx:a,dy:n}=(0,o.getDistances)(e,t),c=Math.atan2(n,a),T=o.Vector.create(Math.sin(c),-Math.cos(c)),E=_*(s.x*T.x+s.y*T.y);T.multTo(E),s.subFrom(T)}}}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*! tsParticles Polygon Mask Plugin v3.2.1 by Matteo Bruni */
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { deepExtend, errorPrefix, getDistance, getDistances, getRandom, isArray, isString, itemFromArray, percentDenominator, } from "@tsparticles/engine";
|
|
2
|
-
import { calcClosestPtOnSegment, drawPolygonMask, drawPolygonMaskPath, parsePaths, segmentBounce } from "./utils.js";
|
|
3
2
|
const noPolygonDataLoaded = `${errorPrefix} No polygon data loaded.`, noPolygonFound = `${errorPrefix} No polygon found, you need to specify SVG url in config.`, origin = {
|
|
4
3
|
x: 0,
|
|
5
4
|
y: 0,
|
|
@@ -76,14 +75,14 @@ export class PolygonMaskInstance {
|
|
|
76
75
|
if (!req.ok) {
|
|
77
76
|
throw new Error(`${errorPrefix} occurred during polygon mask download`);
|
|
78
77
|
}
|
|
79
|
-
return this._parseSvgPath(await req.text(), force);
|
|
78
|
+
return await this._parseSvgPath(await req.text(), force);
|
|
80
79
|
};
|
|
81
80
|
this._drawPoints = () => {
|
|
82
81
|
if (!this.raw) {
|
|
83
82
|
return;
|
|
84
83
|
}
|
|
85
84
|
for (const item of this.raw) {
|
|
86
|
-
this._container.particles.addParticle({
|
|
85
|
+
void this._container.particles.addParticle({
|
|
87
86
|
x: item.x,
|
|
88
87
|
y: item.y,
|
|
89
88
|
});
|
|
@@ -168,14 +167,14 @@ export class PolygonMaskInstance {
|
|
|
168
167
|
const namespaces = 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"';
|
|
169
168
|
svg = `<svg ${namespaces} width="${data.size.width}" height="${data.size.height}">${path}</svg>`;
|
|
170
169
|
}
|
|
171
|
-
this.raw = this._parseSvgPath(svg, force);
|
|
170
|
+
this.raw = await this._parseSvgPath(svg, force);
|
|
172
171
|
}
|
|
173
172
|
this._createPath2D();
|
|
174
173
|
this._engine.dispatchEvent("polygonMaskLoaded", {
|
|
175
174
|
container: this._container,
|
|
176
175
|
});
|
|
177
176
|
};
|
|
178
|
-
this._parseSvgPath = (xml, force) => {
|
|
177
|
+
this._parseSvgPath = async (xml, force) => {
|
|
179
178
|
const forceDownload = force ?? false;
|
|
180
179
|
if (this.paths !== undefined && !forceDownload) {
|
|
181
180
|
return this.raw;
|
|
@@ -210,9 +209,10 @@ export class PolygonMaskInstance {
|
|
|
210
209
|
x: (canvasSize.width * position.x) / percentDenominator - this.dimension.width * half,
|
|
211
210
|
y: (canvasSize.height * position.y) / percentDenominator - this.dimension.height * half,
|
|
212
211
|
};
|
|
212
|
+
const { parsePaths } = await import("./utils.js");
|
|
213
213
|
return parsePaths(this.paths, scale, this.offset);
|
|
214
214
|
};
|
|
215
|
-
this._polygonBounce = (particle,
|
|
215
|
+
this._polygonBounce = async (particle, delta, direction) => {
|
|
216
216
|
const options = this._container.actualOptions.polygon;
|
|
217
217
|
if (!this.raw || !options?.enable || direction !== "top") {
|
|
218
218
|
return false;
|
|
@@ -221,11 +221,12 @@ export class PolygonMaskInstance {
|
|
|
221
221
|
let closest, dx, dy;
|
|
222
222
|
const pos = particle.getPosition(), radius = particle.getRadius(), offset = 1;
|
|
223
223
|
for (let i = 0, j = this.raw.length - offset; i < this.raw.length; j = i++) {
|
|
224
|
-
const pi = this.raw[i], pj = this.raw[j];
|
|
225
|
-
closest =
|
|
224
|
+
const pi = this.raw[i], pj = this.raw[j], { calcClosestPointOnSegment } = await import("./utils.js");
|
|
225
|
+
closest = calcClosestPointOnSegment(pi, pj, pos);
|
|
226
226
|
const dist = getDistances(pos, closest);
|
|
227
227
|
[dx, dy] = [dist.dx, dist.dy];
|
|
228
228
|
if (dist.distance < radius) {
|
|
229
|
+
const { segmentBounce } = await import("./utils.js");
|
|
229
230
|
segmentBounce(pi, pj, particle.velocity);
|
|
230
231
|
return true;
|
|
231
232
|
}
|
|
@@ -307,7 +308,7 @@ export class PolygonMaskInstance {
|
|
|
307
308
|
options.type !== "inline" &&
|
|
308
309
|
this._checkInsidePolygon(position));
|
|
309
310
|
}
|
|
310
|
-
draw(context) {
|
|
311
|
+
async draw(context) {
|
|
311
312
|
if (!this.paths?.length) {
|
|
312
313
|
return;
|
|
313
314
|
}
|
|
@@ -326,9 +327,11 @@ export class PolygonMaskInstance {
|
|
|
326
327
|
continue;
|
|
327
328
|
}
|
|
328
329
|
if (path2d && this.offset) {
|
|
330
|
+
const { drawPolygonMaskPath } = await import("./utils.js");
|
|
329
331
|
drawPolygonMaskPath(context, path2d, polygonDraw.stroke, this.offset);
|
|
330
332
|
}
|
|
331
333
|
else if (rawData) {
|
|
334
|
+
const { drawPolygonMask } = await import("./utils.js");
|
|
332
335
|
drawPolygonMask(context, rawData, polygonDraw.stroke);
|
|
333
336
|
}
|
|
334
337
|
}
|
|
@@ -344,8 +347,8 @@ export class PolygonMaskInstance {
|
|
|
344
347
|
await this._initRawData();
|
|
345
348
|
}
|
|
346
349
|
}
|
|
347
|
-
particleBounce(particle, delta, direction) {
|
|
348
|
-
return this._polygonBounce(particle, delta, direction);
|
|
350
|
+
async particleBounce(particle, delta, direction) {
|
|
351
|
+
return await this._polygonBounce(particle, delta, direction);
|
|
349
352
|
}
|
|
350
353
|
particlePosition(position) {
|
|
351
354
|
const options = this._container.actualOptions.polygon, defaultLength = 0;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PolygonMask } from "./Options/Classes/PolygonMask.js";
|
|
2
|
+
export class PolygonMaskPlugin {
|
|
3
|
+
constructor(engine) {
|
|
4
|
+
this.id = "polygonMask";
|
|
5
|
+
this._engine = engine;
|
|
6
|
+
}
|
|
7
|
+
async getPlugin(container) {
|
|
8
|
+
const { PolygonMaskInstance } = await import("./PolygonMaskInstance.js");
|
|
9
|
+
return new PolygonMaskInstance(container, this._engine);
|
|
10
|
+
}
|
|
11
|
+
loadOptions(options, source) {
|
|
12
|
+
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let polygonOptions = options.polygon;
|
|
16
|
+
if (polygonOptions?.load === undefined) {
|
|
17
|
+
options.polygon = polygonOptions = new PolygonMask();
|
|
18
|
+
}
|
|
19
|
+
polygonOptions.load(source?.polygon);
|
|
20
|
+
}
|
|
21
|
+
needsPlugin(options) {
|
|
22
|
+
return (options?.polygon?.enable ??
|
|
23
|
+
(options?.polygon?.type !== undefined && options.polygon.type !== "none"));
|
|
24
|
+
}
|
|
25
|
+
}
|
package/browser/index.js
CHANGED
|
@@ -1,30 +1,6 @@
|
|
|
1
1
|
import "./pathseg.js";
|
|
2
|
-
import { PolygonMask } from "./Options/Classes/PolygonMask.js";
|
|
3
|
-
import { PolygonMaskInstance } from "./PolygonMaskInstance.js";
|
|
4
|
-
class PolygonMaskPlugin {
|
|
5
|
-
constructor(engine) {
|
|
6
|
-
this.id = "polygonMask";
|
|
7
|
-
this._engine = engine;
|
|
8
|
-
}
|
|
9
|
-
getPlugin(container) {
|
|
10
|
-
return new PolygonMaskInstance(container, this._engine);
|
|
11
|
-
}
|
|
12
|
-
loadOptions(options, source) {
|
|
13
|
-
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
let polygonOptions = options.polygon;
|
|
17
|
-
if (polygonOptions?.load === undefined) {
|
|
18
|
-
options.polygon = polygonOptions = new PolygonMask();
|
|
19
|
-
}
|
|
20
|
-
polygonOptions.load(source?.polygon);
|
|
21
|
-
}
|
|
22
|
-
needsPlugin(options) {
|
|
23
|
-
return (options?.polygon?.enable ??
|
|
24
|
-
(options?.polygon?.type !== undefined && options.polygon.type !== "none"));
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
2
|
export async function loadPolygonMaskPlugin(engine, refresh = true) {
|
|
3
|
+
const { PolygonMaskPlugin } = await import("./PolygonMaskPlugin.js");
|
|
28
4
|
await engine.addPlugin(new PolygonMaskPlugin(engine), refresh);
|
|
29
5
|
}
|
|
30
6
|
export * from "./Enums/PolygonMaskInlineArrangement.js";
|
package/browser/utils.js
CHANGED
|
@@ -94,7 +94,7 @@ export function parsePaths(paths, scale, offset) {
|
|
|
94
94
|
}
|
|
95
95
|
return res;
|
|
96
96
|
}
|
|
97
|
-
export function
|
|
97
|
+
export function calcClosestPointOnSegment(s1, s2, pos) {
|
|
98
98
|
const { dx: dx1, dy: dy1 } = getDistances(pos, s1), { dx: dx2, dy: dy2 } = getDistances(s2, s1), t = (dx1 * dx2 + dy1 * dy2) / (dx2 ** squareExp + dy2 ** squareExp), res = {
|
|
99
99
|
x: s1.x + dx2 * t,
|
|
100
100
|
y: s1.y + dy2 * t,
|
|
@@ -1,8 +1,30 @@
|
|
|
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.PolygonMaskInstance = void 0;
|
|
4
27
|
const engine_1 = require("@tsparticles/engine");
|
|
5
|
-
const utils_js_1 = require("./utils.js");
|
|
6
28
|
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 = {
|
|
7
29
|
x: 0,
|
|
8
30
|
y: 0,
|
|
@@ -79,14 +101,14 @@ class PolygonMaskInstance {
|
|
|
79
101
|
if (!req.ok) {
|
|
80
102
|
throw new Error(`${engine_1.errorPrefix} occurred during polygon mask download`);
|
|
81
103
|
}
|
|
82
|
-
return this._parseSvgPath(await req.text(), force);
|
|
104
|
+
return await this._parseSvgPath(await req.text(), force);
|
|
83
105
|
};
|
|
84
106
|
this._drawPoints = () => {
|
|
85
107
|
if (!this.raw) {
|
|
86
108
|
return;
|
|
87
109
|
}
|
|
88
110
|
for (const item of this.raw) {
|
|
89
|
-
this._container.particles.addParticle({
|
|
111
|
+
void this._container.particles.addParticle({
|
|
90
112
|
x: item.x,
|
|
91
113
|
y: item.y,
|
|
92
114
|
});
|
|
@@ -171,14 +193,14 @@ class PolygonMaskInstance {
|
|
|
171
193
|
const namespaces = 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"';
|
|
172
194
|
svg = `<svg ${namespaces} width="${data.size.width}" height="${data.size.height}">${path}</svg>`;
|
|
173
195
|
}
|
|
174
|
-
this.raw = this._parseSvgPath(svg, force);
|
|
196
|
+
this.raw = await this._parseSvgPath(svg, force);
|
|
175
197
|
}
|
|
176
198
|
this._createPath2D();
|
|
177
199
|
this._engine.dispatchEvent("polygonMaskLoaded", {
|
|
178
200
|
container: this._container,
|
|
179
201
|
});
|
|
180
202
|
};
|
|
181
|
-
this._parseSvgPath = (xml, force) => {
|
|
203
|
+
this._parseSvgPath = async (xml, force) => {
|
|
182
204
|
const forceDownload = force ?? false;
|
|
183
205
|
if (this.paths !== undefined && !forceDownload) {
|
|
184
206
|
return this.raw;
|
|
@@ -213,9 +235,10 @@ class PolygonMaskInstance {
|
|
|
213
235
|
x: (canvasSize.width * position.x) / engine_1.percentDenominator - this.dimension.width * half,
|
|
214
236
|
y: (canvasSize.height * position.y) / engine_1.percentDenominator - this.dimension.height * half,
|
|
215
237
|
};
|
|
216
|
-
|
|
238
|
+
const { parsePaths } = await Promise.resolve().then(() => __importStar(require("./utils.js")));
|
|
239
|
+
return parsePaths(this.paths, scale, this.offset);
|
|
217
240
|
};
|
|
218
|
-
this._polygonBounce = (particle,
|
|
241
|
+
this._polygonBounce = async (particle, delta, direction) => {
|
|
219
242
|
const options = this._container.actualOptions.polygon;
|
|
220
243
|
if (!this.raw || !options?.enable || direction !== "top") {
|
|
221
244
|
return false;
|
|
@@ -224,12 +247,13 @@ class PolygonMaskInstance {
|
|
|
224
247
|
let closest, dx, dy;
|
|
225
248
|
const pos = particle.getPosition(), radius = particle.getRadius(), offset = 1;
|
|
226
249
|
for (let i = 0, j = this.raw.length - offset; i < this.raw.length; j = i++) {
|
|
227
|
-
const pi = this.raw[i], pj = this.raw[j];
|
|
228
|
-
closest = (
|
|
250
|
+
const pi = this.raw[i], pj = this.raw[j], { calcClosestPointOnSegment } = await Promise.resolve().then(() => __importStar(require("./utils.js")));
|
|
251
|
+
closest = calcClosestPointOnSegment(pi, pj, pos);
|
|
229
252
|
const dist = (0, engine_1.getDistances)(pos, closest);
|
|
230
253
|
[dx, dy] = [dist.dx, dist.dy];
|
|
231
254
|
if (dist.distance < radius) {
|
|
232
|
-
|
|
255
|
+
const { segmentBounce } = await Promise.resolve().then(() => __importStar(require("./utils.js")));
|
|
256
|
+
segmentBounce(pi, pj, particle.velocity);
|
|
233
257
|
return true;
|
|
234
258
|
}
|
|
235
259
|
}
|
|
@@ -310,7 +334,7 @@ class PolygonMaskInstance {
|
|
|
310
334
|
options.type !== "inline" &&
|
|
311
335
|
this._checkInsidePolygon(position));
|
|
312
336
|
}
|
|
313
|
-
draw(context) {
|
|
337
|
+
async draw(context) {
|
|
314
338
|
if (!this.paths?.length) {
|
|
315
339
|
return;
|
|
316
340
|
}
|
|
@@ -329,10 +353,12 @@ class PolygonMaskInstance {
|
|
|
329
353
|
continue;
|
|
330
354
|
}
|
|
331
355
|
if (path2d && this.offset) {
|
|
332
|
-
|
|
356
|
+
const { drawPolygonMaskPath } = await Promise.resolve().then(() => __importStar(require("./utils.js")));
|
|
357
|
+
drawPolygonMaskPath(context, path2d, polygonDraw.stroke, this.offset);
|
|
333
358
|
}
|
|
334
359
|
else if (rawData) {
|
|
335
|
-
|
|
360
|
+
const { drawPolygonMask } = await Promise.resolve().then(() => __importStar(require("./utils.js")));
|
|
361
|
+
drawPolygonMask(context, rawData, polygonDraw.stroke);
|
|
336
362
|
}
|
|
337
363
|
}
|
|
338
364
|
}
|
|
@@ -347,8 +373,8 @@ class PolygonMaskInstance {
|
|
|
347
373
|
await this._initRawData();
|
|
348
374
|
}
|
|
349
375
|
}
|
|
350
|
-
particleBounce(particle, delta, direction) {
|
|
351
|
-
return this._polygonBounce(particle, delta, direction);
|
|
376
|
+
async particleBounce(particle, delta, direction) {
|
|
377
|
+
return await this._polygonBounce(particle, delta, direction);
|
|
352
378
|
}
|
|
353
379
|
particlePosition(position) {
|
|
354
380
|
const options = this._container.actualOptions.polygon, defaultLength = 0;
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.PolygonMaskPlugin = void 0;
|
|
27
|
+
const PolygonMask_js_1 = require("./Options/Classes/PolygonMask.js");
|
|
28
|
+
class PolygonMaskPlugin {
|
|
29
|
+
constructor(engine) {
|
|
30
|
+
this.id = "polygonMask";
|
|
31
|
+
this._engine = engine;
|
|
32
|
+
}
|
|
33
|
+
async getPlugin(container) {
|
|
34
|
+
const { PolygonMaskInstance } = await Promise.resolve().then(() => __importStar(require("./PolygonMaskInstance.js")));
|
|
35
|
+
return new PolygonMaskInstance(container, this._engine);
|
|
36
|
+
}
|
|
37
|
+
loadOptions(options, source) {
|
|
38
|
+
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let polygonOptions = options.polygon;
|
|
42
|
+
if (polygonOptions?.load === undefined) {
|
|
43
|
+
options.polygon = polygonOptions = new PolygonMask_js_1.PolygonMask();
|
|
44
|
+
}
|
|
45
|
+
polygonOptions.load(source?.polygon);
|
|
46
|
+
}
|
|
47
|
+
needsPlugin(options) {
|
|
48
|
+
return (options?.polygon?.enable ??
|
|
49
|
+
(options?.polygon?.type !== undefined && options.polygon.type !== "none"));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.PolygonMaskPlugin = PolygonMaskPlugin;
|
package/cjs/index.js
CHANGED
|
@@ -10,38 +10,26 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
10
10
|
if (k2 === undefined) k2 = k;
|
|
11
11
|
o[k2] = m[k];
|
|
12
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
|
+
};
|
|
13
25
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
26
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
27
|
};
|
|
16
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
29
|
exports.loadPolygonMaskPlugin = void 0;
|
|
18
30
|
require("./pathseg.js");
|
|
19
|
-
const PolygonMask_js_1 = require("./Options/Classes/PolygonMask.js");
|
|
20
|
-
const PolygonMaskInstance_js_1 = require("./PolygonMaskInstance.js");
|
|
21
|
-
class PolygonMaskPlugin {
|
|
22
|
-
constructor(engine) {
|
|
23
|
-
this.id = "polygonMask";
|
|
24
|
-
this._engine = engine;
|
|
25
|
-
}
|
|
26
|
-
getPlugin(container) {
|
|
27
|
-
return new PolygonMaskInstance_js_1.PolygonMaskInstance(container, this._engine);
|
|
28
|
-
}
|
|
29
|
-
loadOptions(options, source) {
|
|
30
|
-
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
let polygonOptions = options.polygon;
|
|
34
|
-
if (polygonOptions?.load === undefined) {
|
|
35
|
-
options.polygon = polygonOptions = new PolygonMask_js_1.PolygonMask();
|
|
36
|
-
}
|
|
37
|
-
polygonOptions.load(source?.polygon);
|
|
38
|
-
}
|
|
39
|
-
needsPlugin(options) {
|
|
40
|
-
return (options?.polygon?.enable ??
|
|
41
|
-
(options?.polygon?.type !== undefined && options.polygon.type !== "none"));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
31
|
async function loadPolygonMaskPlugin(engine, refresh = true) {
|
|
32
|
+
const { PolygonMaskPlugin } = await Promise.resolve().then(() => __importStar(require("./PolygonMaskPlugin.js")));
|
|
45
33
|
await engine.addPlugin(new PolygonMaskPlugin(engine), refresh);
|
|
46
34
|
}
|
|
47
35
|
exports.loadPolygonMaskPlugin = loadPolygonMaskPlugin;
|
package/cjs/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.segmentBounce = exports.
|
|
3
|
+
exports.segmentBounce = exports.calcClosestPointOnSegment = exports.parsePaths = exports.drawPolygonMaskPath = exports.drawPolygonMask = void 0;
|
|
4
4
|
const engine_1 = require("@tsparticles/engine");
|
|
5
5
|
const squareExp = 2, inSegmentRange = {
|
|
6
6
|
min: 0,
|
|
@@ -100,7 +100,7 @@ function parsePaths(paths, scale, offset) {
|
|
|
100
100
|
return res;
|
|
101
101
|
}
|
|
102
102
|
exports.parsePaths = parsePaths;
|
|
103
|
-
function
|
|
103
|
+
function calcClosestPointOnSegment(s1, s2, pos) {
|
|
104
104
|
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 = {
|
|
105
105
|
x: s1.x + dx2 * t,
|
|
106
106
|
y: s1.y + dy2 * t,
|
|
@@ -116,7 +116,7 @@ function calcClosestPtOnSegment(s1, s2, pos) {
|
|
|
116
116
|
}
|
|
117
117
|
return res;
|
|
118
118
|
}
|
|
119
|
-
exports.
|
|
119
|
+
exports.calcClosestPointOnSegment = calcClosestPointOnSegment;
|
|
120
120
|
function segmentBounce(start, stop, velocity) {
|
|
121
121
|
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);
|
|
122
122
|
wallNormal.multTo(d);
|
|
@@ -0,0 +1,30 @@
|
|
|
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.1
|
|
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_polygon_mask"] = this["webpackChunk_tsparticles_plugin_polygon_mask"] || []).push([["dist_browser_PolygonMaskInstance_js"],{
|
|
19
|
+
|
|
20
|
+
/***/ "./dist/browser/PolygonMaskInstance.js":
|
|
21
|
+
/*!*********************************************!*\
|
|
22
|
+
!*** ./dist/browser/PolygonMaskInstance.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 */ PolygonMaskInstance: () => (/* binding */ PolygonMaskInstance)\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 noPolygonDataLoaded = `${_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.errorPrefix} No polygon data loaded.`,\n noPolygonFound = `${_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.errorPrefix} No polygon found, you need to specify SVG url in config.`,\n origin = {\n x: 0,\n y: 0\n },\n half = 0.5,\n double = 2;\nclass PolygonMaskInstance {\n constructor(container, engine) {\n this._checkInsidePolygon = position => {\n const container = this._container,\n options = container.actualOptions.polygon;\n if (!options?.enable || options.type === \"none\" || options.type === \"inline\") {\n return true;\n }\n if (!this.raw) {\n throw new Error(noPolygonFound);\n }\n const canvasSize = container.canvas.size,\n x = position?.x ?? (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRandom)() * canvasSize.width,\n y = position?.y ?? (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRandom)() * canvasSize.height,\n indexOffset = 1;\n let inside = false;\n for (let i = 0, j = this.raw.length - indexOffset; i < this.raw.length; j = i++) {\n const pi = this.raw[i],\n pj = this.raw[j],\n intersect = pi.y > y !== pj.y > y && x < (pj.x - pi.x) * (y - pi.y) / (pj.y - pi.y) + pi.x;\n if (intersect) {\n inside = !inside;\n }\n }\n if (options.type === \"inside\") {\n return inside;\n } else {\n return options.type === \"outside\" ? !inside : false;\n }\n };\n this._createPath2D = () => {\n const container = this._container,\n options = container.actualOptions.polygon;\n if (!options || !this.paths?.length) {\n return;\n }\n for (const path of this.paths) {\n const pathData = path.element?.getAttribute(\"d\");\n if (pathData) {\n const path2d = new Path2D(pathData),\n matrix = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\").createSVGMatrix(),\n finalPath = new Path2D(),\n transform = matrix.scale(this._scale);\n if (finalPath.addPath) {\n finalPath.addPath(path2d, transform);\n path.path2d = finalPath;\n } else {\n delete path.path2d;\n }\n } else {\n delete path.path2d;\n }\n if (path.path2d ?? !this.raw) {\n continue;\n }\n path.path2d = new Path2D();\n const firstIndex = 0,\n firstPoint = this.raw[firstIndex];\n path.path2d.moveTo(firstPoint.x, firstPoint.y);\n this.raw.forEach((pos, i) => {\n if (i > firstIndex) {\n path.path2d?.lineTo(pos.x, pos.y);\n }\n });\n path.path2d.closePath();\n }\n };\n this._downloadSvgPath = async (svgUrl, force) => {\n const options = this._container.actualOptions.polygon;\n if (!options) {\n return;\n }\n const url = svgUrl ?? options.url,\n forceDownload = force ?? false;\n if (!url || this.paths !== undefined && !forceDownload) {\n return this.raw;\n }\n const req = await fetch(url);\n if (!req.ok) {\n throw new Error(`${_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.errorPrefix} occurred during polygon mask download`);\n }\n return await this._parseSvgPath(await req.text(), force);\n };\n this._drawPoints = () => {\n if (!this.raw) {\n return;\n }\n for (const item of this.raw) {\n void this._container.particles.addParticle({\n x: item.x,\n y: item.y\n });\n }\n };\n this._getEquidistantPointByIndex = index => {\n const container = this._container,\n options = container.actualOptions,\n polygonMaskOptions = options.polygon;\n if (!polygonMaskOptions) {\n return;\n }\n if (!this.raw?.length || !this.paths?.length) {\n throw new Error(noPolygonDataLoaded);\n }\n let offset = 0,\n point;\n const baseAccumulator = 0,\n totalLength = this.paths.reduce((tot, path) => tot + path.length, baseAccumulator),\n distance = totalLength / options.particles.number.value;\n for (const path of this.paths) {\n const pathDistance = distance * index - offset;\n if (pathDistance <= path.length) {\n point = path.element.getPointAtLength(pathDistance);\n break;\n } else {\n offset += path.length;\n }\n }\n const scale = this._scale;\n return {\n x: (point?.x ?? origin.x) * scale + (this.offset?.x ?? origin.x),\n y: (point?.y ?? origin.y) * scale + (this.offset?.y ?? origin.y)\n };\n };\n this._getPointByIndex = index => {\n if (!this.raw?.length) {\n throw new Error(noPolygonDataLoaded);\n }\n const coords = this.raw[index % this.raw.length];\n return {\n x: coords.x,\n y: coords.y\n };\n };\n this._getRandomPoint = () => {\n if (!this.raw?.length) {\n throw new Error(noPolygonDataLoaded);\n }\n const coords = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.itemFromArray)(this.raw);\n return {\n x: coords.x,\n y: coords.y\n };\n };\n this._getRandomPointByLength = () => {\n const container = this._container,\n options = container.actualOptions.polygon;\n if (!options) {\n return;\n }\n if (!this.raw?.length || !this.paths?.length) {\n throw new Error(noPolygonDataLoaded);\n }\n const path = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.itemFromArray)(this.paths),\n offset = 1,\n distance = Math.floor((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRandom)() * path.length) + offset,\n point = path.element.getPointAtLength(distance),\n scale = this._scale;\n return {\n x: point.x * scale + (this.offset?.x ?? origin.x),\n y: point.y * scale + (this.offset?.y ?? origin.y)\n };\n };\n this._initRawData = async force => {\n const options = this._container.actualOptions.polygon;\n if (!options) {\n return;\n }\n if (options.url) {\n this.raw = await this._downloadSvgPath(options.url, force);\n } else if (options.data) {\n const data = options.data;\n let svg;\n if ((0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isString)(data)) {\n svg = data;\n } else {\n const getPath = p => `<path d=\"${p}\" />`,\n path = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.isArray)(data.path) ? data.path.map(getPath).join(\"\") : getPath(data.path);\n const namespaces = 'xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"';\n svg = `<svg ${namespaces} width=\"${data.size.width}\" height=\"${data.size.height}\">${path}</svg>`;\n }\n this.raw = await this._parseSvgPath(svg, force);\n }\n this._createPath2D();\n this._engine.dispatchEvent(\"polygonMaskLoaded\", {\n container: this._container\n });\n };\n this._parseSvgPath = async (xml, force) => {\n const forceDownload = force ?? false;\n if (this.paths !== undefined && !forceDownload) {\n return this.raw;\n }\n const container = this._container,\n options = container.actualOptions.polygon;\n if (!options) {\n return;\n }\n const parser = new DOMParser(),\n doc = parser.parseFromString(xml, \"image/svg+xml\"),\n firstIndex = 0,\n svg = doc.getElementsByTagName(\"svg\")[firstIndex];\n let svgPaths = svg.getElementsByTagName(\"path\");\n if (!svgPaths.length) {\n svgPaths = doc.getElementsByTagName(\"path\");\n }\n this.paths = [];\n for (let i = 0; i < svgPaths.length; i++) {\n const path = svgPaths.item(i);\n if (path) {\n this.paths.push({\n element: path,\n length: path.getTotalLength()\n });\n }\n }\n const scale = this._scale;\n this.dimension.width = parseFloat(svg.getAttribute(\"width\") ?? \"0\") * scale;\n this.dimension.height = parseFloat(svg.getAttribute(\"height\") ?? \"0\") * scale;\n const position = options.position ?? {\n x: 50,\n y: 50\n },\n canvasSize = container.canvas.size;\n this.offset = {\n x: canvasSize.width * position.x / _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.percentDenominator - this.dimension.width * half,\n y: canvasSize.height * position.y / _tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.percentDenominator - this.dimension.height * half\n };\n const {\n parsePaths\n } = await __webpack_require__.e(/*! import() */ \"dist_browser_utils_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./utils.js */ \"./dist/browser/utils.js\"));\n return parsePaths(this.paths, scale, this.offset);\n };\n this._polygonBounce = async (particle, delta, direction) => {\n const options = this._container.actualOptions.polygon;\n if (!this.raw || !options?.enable || direction !== \"top\") {\n return false;\n }\n if (options.type === \"inside\" || options.type === \"outside\") {\n let closest, dx, dy;\n const pos = particle.getPosition(),\n radius = particle.getRadius(),\n offset = 1;\n for (let i = 0, j = this.raw.length - offset; i < this.raw.length; j = i++) {\n const pi = this.raw[i],\n pj = this.raw[j],\n {\n calcClosestPointOnSegment\n } = await __webpack_require__.e(/*! import() */ \"dist_browser_utils_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./utils.js */ \"./dist/browser/utils.js\"));\n closest = calcClosestPointOnSegment(pi, pj, pos);\n const dist = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistances)(pos, closest);\n [dx, dy] = [dist.dx, dist.dy];\n if (dist.distance < radius) {\n const {\n segmentBounce\n } = await __webpack_require__.e(/*! import() */ \"dist_browser_utils_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./utils.js */ \"./dist/browser/utils.js\"));\n segmentBounce(pi, pj, particle.velocity);\n return true;\n }\n }\n if (closest && dx !== undefined && dy !== undefined && !this._checkInsidePolygon(pos)) {\n const factor = {\n x: 1,\n y: 1\n },\n diameter = radius * double,\n inverse = -1;\n if (pos.x >= closest.x) {\n factor.x = -1;\n }\n if (pos.y >= closest.y) {\n factor.y = -1;\n }\n particle.position.x = closest.x + diameter * factor.x;\n particle.position.y = closest.y + diameter * factor.y;\n particle.velocity.mult(inverse);\n return true;\n }\n } else if (options.type === \"inline\" && particle.initialPosition) {\n const dist = (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getDistance)(particle.initialPosition, particle.getPosition()),\n {\n velocity\n } = particle;\n if (dist > this._moveRadius) {\n velocity.x = velocity.y * half - velocity.x;\n velocity.y = velocity.x * half - velocity.y;\n return true;\n }\n }\n return false;\n };\n this._randomPoint = () => {\n const container = this._container,\n options = container.actualOptions.polygon;\n if (!options) {\n return;\n }\n let position;\n if (options.type === \"inline\") {\n switch (options.inline.arrangement) {\n case \"random-point\":\n position = this._getRandomPoint();\n break;\n case \"random-length\":\n position = this._getRandomPointByLength();\n break;\n case \"equidistant\":\n position = this._getEquidistantPointByIndex(container.particles.count);\n break;\n case \"one-per-point\":\n case \"per-point\":\n default:\n position = this._getPointByIndex(container.particles.count);\n }\n } else {\n const canvasSize = container.canvas.size;\n position = {\n x: (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRandom)() * canvasSize.width,\n y: (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.getRandom)() * canvasSize.height\n };\n }\n if (this._checkInsidePolygon(position)) {\n return position;\n } else {\n return this._randomPoint();\n }\n };\n this._container = container;\n this._engine = engine;\n this.dimension = {\n height: 0,\n width: 0\n };\n this._moveRadius = 0;\n this._scale = 1;\n }\n clickPositionValid(position) {\n const options = this._container.actualOptions.polygon;\n return !!options?.enable && options.type !== \"none\" && options.type !== \"inline\" && this._checkInsidePolygon(position);\n }\n async draw(context) {\n if (!this.paths?.length) {\n return;\n }\n const options = this._container.actualOptions.polygon;\n if (!options?.enable) {\n return;\n }\n const polygonDraw = options.draw;\n if (!polygonDraw.enable) {\n return;\n }\n const rawData = this.raw;\n for (const path of this.paths) {\n const path2d = path.path2d;\n if (!context) {\n continue;\n }\n if (path2d && this.offset) {\n const {\n drawPolygonMaskPath\n } = await __webpack_require__.e(/*! import() */ \"dist_browser_utils_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./utils.js */ \"./dist/browser/utils.js\"));\n drawPolygonMaskPath(context, path2d, polygonDraw.stroke, this.offset);\n } else if (rawData) {\n const {\n drawPolygonMask\n } = await __webpack_require__.e(/*! import() */ \"dist_browser_utils_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./utils.js */ \"./dist/browser/utils.js\"));\n drawPolygonMask(context, rawData, polygonDraw.stroke);\n }\n }\n }\n async init() {\n const container = this._container,\n polygonMaskOptions = container.actualOptions.polygon,\n pxRatio = container.retina.pixelRatio;\n if (!polygonMaskOptions) {\n return;\n }\n this._moveRadius = polygonMaskOptions.move.radius * pxRatio;\n this._scale = polygonMaskOptions.scale * pxRatio;\n if (polygonMaskOptions.enable) {\n await this._initRawData();\n }\n }\n async particleBounce(particle, delta, direction) {\n return await this._polygonBounce(particle, delta, direction);\n }\n particlePosition(position) {\n const options = this._container.actualOptions.polygon,\n defaultLength = 0;\n if (!(options?.enable && (this.raw?.length ?? defaultLength) > defaultLength)) {\n return;\n }\n return (0,_tsparticles_engine__WEBPACK_IMPORTED_MODULE_0__.deepExtend)({}, position ? position : this._randomPoint());\n }\n particlesInitialization() {\n const options = this._container.actualOptions.polygon;\n if (options?.enable && options.type === \"inline\" && (options.inline.arrangement === \"one-per-point\" || options.inline.arrangement === \"per-point\")) {\n this._drawPoints();\n return true;\n }\n return false;\n }\n resize() {\n const container = this._container,\n options = container.actualOptions.polygon;\n if (!(options?.enable && options.type !== \"none\")) {\n return;\n }\n if (this.redrawTimeout) {\n clearTimeout(this.redrawTimeout);\n }\n const timeout = 250;\n this.redrawTimeout = window.setTimeout(() => {\n void (async () => {\n await this._initRawData(true);\n await container.particles.redraw();\n })();\n }, timeout);\n }\n stop() {\n delete this.raw;\n delete this.paths;\n }\n}\n\n//# sourceURL=webpack://@tsparticles/plugin-polygon-mask/./dist/browser/PolygonMaskInstance.js?");
|
|
27
|
+
|
|
28
|
+
/***/ })
|
|
29
|
+
|
|
30
|
+
}]);
|