@tsparticles/plugin-poisson-disc 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +74 -0
- package/browser/Interfaces/IPoissonPoint.js +1 -0
- package/browser/Options/Classes/Poisson.js +26 -0
- package/browser/Options/Interfaces/IPoisson.js +1 -0
- package/browser/PoissonDisc.js +138 -0
- package/browser/PoissonInstance.js +55 -0
- package/browser/index.js +27 -0
- package/browser/package.json +1 -0
- package/browser/types.js +1 -0
- package/cjs/Interfaces/IPoissonPoint.js +2 -0
- package/cjs/Options/Classes/Poisson.js +30 -0
- package/cjs/Options/Interfaces/IPoisson.js +2 -0
- package/cjs/PoissonDisc.js +142 -0
- package/cjs/PoissonInstance.js +59 -0
- package/cjs/index.js +31 -0
- package/cjs/package.json +1 -0
- package/cjs/types.js +2 -0
- package/esm/Interfaces/IPoissonPoint.js +1 -0
- package/esm/Options/Classes/Poisson.js +26 -0
- package/esm/Options/Interfaces/IPoisson.js +1 -0
- package/esm/PoissonDisc.js +138 -0
- package/esm/PoissonInstance.js +55 -0
- package/esm/index.js +27 -0
- package/esm/package.json +1 -0
- package/esm/types.js +1 -0
- package/package.json +93 -0
- package/report.html +39 -0
- package/tsparticles.plugin.poisson.js +366 -0
- package/tsparticles.plugin.poisson.min.js +2 -0
- package/tsparticles.plugin.poisson.min.js.LICENSE.txt +1 -0
- package/types/Interfaces/IPoissonPoint.d.ts +5 -0
- package/types/Options/Classes/Poisson.d.ts +11 -0
- package/types/Options/Interfaces/IPoisson.d.ts +7 -0
- package/types/PoissonDisc.d.ts +27 -0
- package/types/PoissonInstance.d.ts +16 -0
- package/types/index.d.ts +2 -0
- package/types/types.d.ts +12 -0
- package/umd/Interfaces/IPoissonPoint.js +12 -0
- package/umd/Options/Classes/Poisson.js +40 -0
- package/umd/Options/Interfaces/IPoisson.js +12 -0
- package/umd/PoissonDisc.js +152 -0
- package/umd/PoissonInstance.js +69 -0
- package/umd/index.js +41 -0
- package/umd/types.js +12 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { getDistance, getRandom } from "@tsparticles/engine";
|
|
2
|
+
const double = 2, doublePI = Math.PI * double;
|
|
3
|
+
export class PoissonDisc {
|
|
4
|
+
constructor(size, radius, retries, dimensions, firstPoint) {
|
|
5
|
+
this.size = { ...size };
|
|
6
|
+
this.radius = radius;
|
|
7
|
+
this.retries = retries;
|
|
8
|
+
this.dimensions = dimensions;
|
|
9
|
+
this.cellSize = Math.floor(this.radius / Math.sqrt(this.dimensions));
|
|
10
|
+
this.cols = Math.floor(this.size.width / this.cellSize);
|
|
11
|
+
this.rows = Math.floor(this.size.height / this.cellSize);
|
|
12
|
+
this.points = [];
|
|
13
|
+
this.active = [];
|
|
14
|
+
this.grid = [];
|
|
15
|
+
this.firstPoint = firstPoint ? { ...firstPoint } : undefined;
|
|
16
|
+
this.reset();
|
|
17
|
+
}
|
|
18
|
+
addPoint(inputPoint) {
|
|
19
|
+
const point = {
|
|
20
|
+
position: { ...inputPoint },
|
|
21
|
+
gridPosition: {
|
|
22
|
+
x: Math.floor(inputPoint.x / this.cellSize),
|
|
23
|
+
y: Math.floor(inputPoint.y / this.cellSize),
|
|
24
|
+
},
|
|
25
|
+
}, pointIndex = this.points.length;
|
|
26
|
+
this.points.push(point);
|
|
27
|
+
this.grid[point.gridPosition.y][point.gridPosition.x] = pointIndex;
|
|
28
|
+
this.active.push(pointIndex);
|
|
29
|
+
}
|
|
30
|
+
getRandom(min, max) {
|
|
31
|
+
return Math.floor(getRandom() * (max - min)) + min;
|
|
32
|
+
}
|
|
33
|
+
initialiseGrid() {
|
|
34
|
+
for (let y = 0; y <= this.rows; y++) {
|
|
35
|
+
this.grid[y] = [];
|
|
36
|
+
for (let x = 0; x <= this.cols; x++) {
|
|
37
|
+
this.grid[y][x] = -1;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
reset() {
|
|
42
|
+
this.points = [];
|
|
43
|
+
this.active = [];
|
|
44
|
+
this.grid = [];
|
|
45
|
+
this.initialiseGrid();
|
|
46
|
+
if (this.firstPoint) {
|
|
47
|
+
this.addPoint(this.firstPoint);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const minCoordinate = 0;
|
|
51
|
+
this.addPoint({
|
|
52
|
+
x: this.getRandom(minCoordinate, this.size.width),
|
|
53
|
+
y: this.getRandom(minCoordinate, this.size.height),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async run() {
|
|
58
|
+
this.reset();
|
|
59
|
+
const minCount = 0, step = 1;
|
|
60
|
+
while (this.active.length > minCount) {
|
|
61
|
+
await this.steps(step);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async steps(steps) {
|
|
65
|
+
const minCount = 0;
|
|
66
|
+
for (let i = 0; i < steps; i++) {
|
|
67
|
+
if (this.active.length <= minCount) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
await this._step();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
_getNewPoint(currentPoint, tries) {
|
|
74
|
+
const minCoordinate = 0, gridMinValue = 0, maxNeighbourIndex = 1, newAngle = tries * (doublePI / this.retries), newDist = this.getRandom(this.radius, this.radius * double), offset = {
|
|
75
|
+
x: Math.cos(newAngle) * newDist,
|
|
76
|
+
y: Math.sin(newAngle) * newDist,
|
|
77
|
+
}, newPoint = {
|
|
78
|
+
x: Math.floor(currentPoint.position.x + offset.x),
|
|
79
|
+
y: Math.floor(currentPoint.position.y + offset.y),
|
|
80
|
+
}, newGridCoords = {
|
|
81
|
+
x: Math.floor(newPoint.x / this.cellSize),
|
|
82
|
+
y: Math.floor(newPoint.y / this.cellSize),
|
|
83
|
+
};
|
|
84
|
+
if (newPoint.x > minCoordinate &&
|
|
85
|
+
newPoint.x < this.size.width &&
|
|
86
|
+
newPoint.y > minCoordinate &&
|
|
87
|
+
newPoint.y < this.size.height) {
|
|
88
|
+
if (this.grid[newGridCoords.y][newGridCoords.x] < gridMinValue) {
|
|
89
|
+
for (let i = -1; i <= maxNeighbourIndex; i++) {
|
|
90
|
+
for (let j = -1; j <= maxNeighbourIndex; j++) {
|
|
91
|
+
const neighbourGrid = {
|
|
92
|
+
x: newGridCoords.x + j,
|
|
93
|
+
y: newGridCoords.y + i,
|
|
94
|
+
};
|
|
95
|
+
if (neighbourGrid.x >= minCoordinate &&
|
|
96
|
+
neighbourGrid.y >= minCoordinate &&
|
|
97
|
+
neighbourGrid.x < this.cols &&
|
|
98
|
+
neighbourGrid.y < this.rows &&
|
|
99
|
+
(neighbourGrid.x !== newGridCoords.x || neighbourGrid.y !== newGridCoords.y)) {
|
|
100
|
+
if (this.grid[neighbourGrid.y][neighbourGrid.x] >= gridMinValue) {
|
|
101
|
+
const neighbourIndex = this.grid[neighbourGrid.y][neighbourGrid.x], neighbour = this.points[neighbourIndex], dist = getDistance(newPoint, neighbour.position);
|
|
102
|
+
if (dist < this.radius) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
return newPoint;
|
|
118
|
+
}
|
|
119
|
+
async _step() {
|
|
120
|
+
const minCount = 0, randomActive = this.getRandom(minCount, this.active.length);
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
let foundNewPoint = false;
|
|
123
|
+
for (let tries = 0; tries < this.retries; tries++) {
|
|
124
|
+
const newPoint = this._getNewPoint(this.points[this.active[randomActive]], tries);
|
|
125
|
+
if (newPoint) {
|
|
126
|
+
foundNewPoint = true;
|
|
127
|
+
this.addPoint(newPoint);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (!foundNewPoint) {
|
|
132
|
+
const deleteCount = 1;
|
|
133
|
+
this.active.splice(randomActive, deleteCount);
|
|
134
|
+
}
|
|
135
|
+
resolve();
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getRangeMax } from "@tsparticles/engine";
|
|
2
|
+
import { PoissonDisc } from "./PoissonDisc.js";
|
|
3
|
+
export class PoissonInstance {
|
|
4
|
+
constructor(container, engine) {
|
|
5
|
+
this._container = container;
|
|
6
|
+
this._engine = engine;
|
|
7
|
+
this._currentIndex = 0;
|
|
8
|
+
}
|
|
9
|
+
async init() {
|
|
10
|
+
await this._initData();
|
|
11
|
+
}
|
|
12
|
+
particlePosition(position) {
|
|
13
|
+
const container = this._container, options = container.actualOptions.poisson;
|
|
14
|
+
if (!this.poissonDisc || !(options?.enable ?? false) || this._currentIndex >= this.poissonDisc.points.length) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
return position ?? this.poissonDisc?.points[this._currentIndex++]?.position;
|
|
18
|
+
}
|
|
19
|
+
resize() {
|
|
20
|
+
const container = this._container, options = container.actualOptions.poisson;
|
|
21
|
+
if (!(options?.enable ?? false)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (this.redrawTimeout) {
|
|
25
|
+
clearTimeout(this.redrawTimeout);
|
|
26
|
+
}
|
|
27
|
+
const timeout = 250;
|
|
28
|
+
this.redrawTimeout = window.setTimeout(() => {
|
|
29
|
+
void (async () => {
|
|
30
|
+
await this._initData();
|
|
31
|
+
await container.particles.redraw();
|
|
32
|
+
})();
|
|
33
|
+
}, timeout);
|
|
34
|
+
}
|
|
35
|
+
stop() {
|
|
36
|
+
delete this.poissonDisc;
|
|
37
|
+
}
|
|
38
|
+
async _initData() {
|
|
39
|
+
const container = this._container, poissonOptions = container.actualOptions.poisson, particlesOptions = container.actualOptions.particles, canvasSize = container.canvas.size, pixelRatio = container.retina.pixelRatio;
|
|
40
|
+
if (!poissonOptions?.enable) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this._currentIndex = 0;
|
|
44
|
+
this.poissonDisc = new PoissonDisc(canvasSize, poissonOptions.radius
|
|
45
|
+
? poissonOptions.radius * pixelRatio
|
|
46
|
+
: Math.max(getRangeMax(particlesOptions.size.value) * pixelRatio, Math.sqrt((canvasSize.width * canvasSize.height) / particlesOptions.number.value)), poissonOptions.retries, poissonOptions.dimensions);
|
|
47
|
+
const noSteps = 0;
|
|
48
|
+
if (poissonOptions.steps > noSteps) {
|
|
49
|
+
await this.poissonDisc.steps(poissonOptions.steps);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
await this.poissonDisc.run();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Poisson } from "./Options/Classes/Poisson.js";
|
|
2
|
+
import { PoissonInstance } from "./PoissonInstance.js";
|
|
3
|
+
class PoissonDiscPlugin {
|
|
4
|
+
constructor(engine) {
|
|
5
|
+
this.id = "poisson";
|
|
6
|
+
this._engine = engine;
|
|
7
|
+
}
|
|
8
|
+
getPlugin(container) {
|
|
9
|
+
return new PoissonInstance(container, this._engine);
|
|
10
|
+
}
|
|
11
|
+
loadOptions(options, source) {
|
|
12
|
+
if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let poissonOptions = options.poisson;
|
|
16
|
+
if (poissonOptions?.load === undefined) {
|
|
17
|
+
options.poisson = poissonOptions = new Poisson();
|
|
18
|
+
}
|
|
19
|
+
poissonOptions.load(source?.poisson);
|
|
20
|
+
}
|
|
21
|
+
needsPlugin(options) {
|
|
22
|
+
return options?.poisson?.enable ?? false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function loadPoissonDiscPlugin(engine, refresh = true) {
|
|
26
|
+
await engine.addPlugin(new PoissonDiscPlugin(engine), refresh);
|
|
27
|
+
}
|
package/esm/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "module" }
|
package/esm/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tsparticles/plugin-poisson-disc",
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "tsParticles poisson disc plugin",
|
|
5
|
+
"homepage": "https://particles.js.org",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/tsparticles/tsparticles.git",
|
|
9
|
+
"directory": "plugins/poisson"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"front-end",
|
|
13
|
+
"frontend",
|
|
14
|
+
"tsparticles",
|
|
15
|
+
"particles.js",
|
|
16
|
+
"particlesjs",
|
|
17
|
+
"particles",
|
|
18
|
+
"particle",
|
|
19
|
+
"canvas",
|
|
20
|
+
"jsparticles",
|
|
21
|
+
"xparticles",
|
|
22
|
+
"particles-js",
|
|
23
|
+
"particles-bg",
|
|
24
|
+
"particles-bg-vue",
|
|
25
|
+
"particles-ts",
|
|
26
|
+
"particles.ts",
|
|
27
|
+
"react-particles-js",
|
|
28
|
+
"react-particles.js",
|
|
29
|
+
"react-particles",
|
|
30
|
+
"react",
|
|
31
|
+
"reactjs",
|
|
32
|
+
"vue-particles",
|
|
33
|
+
"ngx-particles",
|
|
34
|
+
"angular-particles",
|
|
35
|
+
"particleground",
|
|
36
|
+
"vue",
|
|
37
|
+
"vuejs",
|
|
38
|
+
"preact",
|
|
39
|
+
"preactjs",
|
|
40
|
+
"jquery",
|
|
41
|
+
"angularjs",
|
|
42
|
+
"angular",
|
|
43
|
+
"typescript",
|
|
44
|
+
"javascript",
|
|
45
|
+
"animation",
|
|
46
|
+
"web",
|
|
47
|
+
"html5",
|
|
48
|
+
"web-design",
|
|
49
|
+
"webdesign",
|
|
50
|
+
"css",
|
|
51
|
+
"html",
|
|
52
|
+
"css3",
|
|
53
|
+
"animated",
|
|
54
|
+
"background",
|
|
55
|
+
"confetti",
|
|
56
|
+
"canvas",
|
|
57
|
+
"fireworks",
|
|
58
|
+
"fireworks-js",
|
|
59
|
+
"confetti-js",
|
|
60
|
+
"confettijs",
|
|
61
|
+
"fireworksjs",
|
|
62
|
+
"canvas-confetti",
|
|
63
|
+
"tsparticles-plugin"
|
|
64
|
+
],
|
|
65
|
+
"author": "Matteo Bruni <matteo.bruni@me.com>",
|
|
66
|
+
"license": "MIT",
|
|
67
|
+
"bugs": {
|
|
68
|
+
"url": "https://github.com/tsparticles/tsparticles/issues"
|
|
69
|
+
},
|
|
70
|
+
"jsdelivr": "tsparticles.plugin.poisson.min.js",
|
|
71
|
+
"unpkg": "tsparticles.plugin.poisson.min.js",
|
|
72
|
+
"browser": "browser/index.js",
|
|
73
|
+
"main": "cjs/index.js",
|
|
74
|
+
"module": "esm/index.js",
|
|
75
|
+
"types": "types/index.d.ts",
|
|
76
|
+
"exports": {
|
|
77
|
+
".": {
|
|
78
|
+
"types": "./types/index.d.ts",
|
|
79
|
+
"browser": "./browser/index.js",
|
|
80
|
+
"import": "./esm/index.js",
|
|
81
|
+
"require": "./cjs/index.js",
|
|
82
|
+
"umd": "./umd/index.js",
|
|
83
|
+
"default": "./cjs/index.js"
|
|
84
|
+
},
|
|
85
|
+
"./package.json": "./package.json"
|
|
86
|
+
},
|
|
87
|
+
"dependencies": {
|
|
88
|
+
"@tsparticles/engine": "^3.1.0"
|
|
89
|
+
},
|
|
90
|
+
"publishConfig": {
|
|
91
|
+
"access": "public"
|
|
92
|
+
}
|
|
93
|
+
}
|