@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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +74 -0
  3. package/browser/Interfaces/IPoissonPoint.js +1 -0
  4. package/browser/Options/Classes/Poisson.js +26 -0
  5. package/browser/Options/Interfaces/IPoisson.js +1 -0
  6. package/browser/PoissonDisc.js +138 -0
  7. package/browser/PoissonInstance.js +55 -0
  8. package/browser/index.js +27 -0
  9. package/browser/package.json +1 -0
  10. package/browser/types.js +1 -0
  11. package/cjs/Interfaces/IPoissonPoint.js +2 -0
  12. package/cjs/Options/Classes/Poisson.js +30 -0
  13. package/cjs/Options/Interfaces/IPoisson.js +2 -0
  14. package/cjs/PoissonDisc.js +142 -0
  15. package/cjs/PoissonInstance.js +59 -0
  16. package/cjs/index.js +31 -0
  17. package/cjs/package.json +1 -0
  18. package/cjs/types.js +2 -0
  19. package/esm/Interfaces/IPoissonPoint.js +1 -0
  20. package/esm/Options/Classes/Poisson.js +26 -0
  21. package/esm/Options/Interfaces/IPoisson.js +1 -0
  22. package/esm/PoissonDisc.js +138 -0
  23. package/esm/PoissonInstance.js +55 -0
  24. package/esm/index.js +27 -0
  25. package/esm/package.json +1 -0
  26. package/esm/types.js +1 -0
  27. package/package.json +93 -0
  28. package/report.html +39 -0
  29. package/tsparticles.plugin.poisson.js +366 -0
  30. package/tsparticles.plugin.poisson.min.js +2 -0
  31. package/tsparticles.plugin.poisson.min.js.LICENSE.txt +1 -0
  32. package/types/Interfaces/IPoissonPoint.d.ts +5 -0
  33. package/types/Options/Classes/Poisson.d.ts +11 -0
  34. package/types/Options/Interfaces/IPoisson.d.ts +7 -0
  35. package/types/PoissonDisc.d.ts +27 -0
  36. package/types/PoissonInstance.d.ts +16 -0
  37. package/types/index.d.ts +2 -0
  38. package/types/types.d.ts +12 -0
  39. package/umd/Interfaces/IPoissonPoint.js +12 -0
  40. package/umd/Options/Classes/Poisson.js +40 -0
  41. package/umd/Options/Interfaces/IPoisson.js +12 -0
  42. package/umd/PoissonDisc.js +152 -0
  43. package/umd/PoissonInstance.js +69 -0
  44. package/umd/index.js +41 -0
  45. 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
+ }
@@ -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
+ }