@tsparticles/engine 3.0.3 → 3.2.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/373.min.js +2 -0
- package/373.min.js.LICENSE.txt +1 -0
- package/438.min.js +2 -0
- package/438.min.js.LICENSE.txt +1 -0
- package/README.md +337 -216
- package/browser/Core/Canvas.js +102 -49
- package/browser/Core/Container.js +53 -41
- package/browser/Core/Engine.js +47 -32
- package/browser/Core/Particle.js +46 -48
- package/browser/Core/Particles.js +70 -57
- package/browser/Core/Retina.js +5 -4
- package/browser/Core/Utils/Circle.js +4 -3
- package/browser/Core/Utils/Constants.js +3 -0
- package/browser/Core/Utils/EventListeners.js +19 -16
- package/browser/Core/Utils/ExternalInteractorBase.js +1 -1
- package/browser/Core/Utils/InteractionManager.js +17 -8
- package/browser/Core/Utils/ParticlesInteractorBase.js +1 -1
- package/browser/Core/Utils/QuadTree.js +5 -3
- package/browser/Core/Utils/Vector.js +7 -2
- package/browser/Core/Utils/Vector3d.js +14 -9
- package/browser/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
- package/browser/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
- package/browser/Options/Classes/ManualParticle.js +3 -2
- package/browser/Options/Classes/Options.js +3 -0
- package/browser/Utils/CanvasUtils.js +50 -40
- package/browser/Utils/ColorUtils.js +124 -45
- package/browser/Utils/EventDispatcher.js +6 -5
- package/browser/Utils/HslColorManager.js +5 -5
- package/browser/Utils/NumberUtils.js +35 -23
- package/browser/Utils/RgbColorManager.js +5 -5
- package/browser/Utils/Utils.js +102 -19
- package/cjs/Core/Canvas.js +102 -49
- package/cjs/Core/Container.js +53 -41
- package/cjs/Core/Engine.js +70 -32
- package/cjs/Core/Particle.js +45 -47
- package/cjs/Core/Particles.js +93 -57
- package/cjs/Core/Retina.js +5 -4
- package/cjs/Core/Utils/Circle.js +4 -3
- package/cjs/Core/Utils/Constants.js +4 -1
- package/cjs/Core/Utils/EventListeners.js +18 -15
- package/cjs/Core/Utils/ExternalInteractorBase.js +1 -1
- package/cjs/Core/Utils/InteractionManager.js +17 -8
- package/cjs/Core/Utils/ParticlesInteractorBase.js +1 -1
- package/cjs/Core/Utils/QuadTree.js +5 -3
- package/cjs/Core/Utils/Vector.js +7 -2
- package/cjs/Core/Utils/Vector3d.js +14 -9
- package/cjs/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
- package/cjs/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
- package/cjs/Options/Classes/ManualParticle.js +3 -2
- package/cjs/Options/Classes/Options.js +3 -0
- package/cjs/Utils/CanvasUtils.js +50 -40
- package/cjs/Utils/ColorUtils.js +126 -45
- package/cjs/Utils/EventDispatcher.js +6 -5
- package/cjs/Utils/HslColorManager.js +5 -5
- package/cjs/Utils/NumberUtils.js +37 -24
- package/cjs/Utils/RgbColorManager.js +5 -5
- package/cjs/Utils/Utils.js +103 -19
- package/dist_browser_Core_Container_js.js +92 -0
- package/dist_browser_Core_Particle_js.js +32 -0
- package/esm/Core/Canvas.js +102 -49
- package/esm/Core/Container.js +53 -41
- package/esm/Core/Engine.js +47 -32
- package/esm/Core/Particle.js +46 -48
- package/esm/Core/Particles.js +70 -57
- package/esm/Core/Retina.js +5 -4
- package/esm/Core/Utils/Circle.js +4 -3
- package/esm/Core/Utils/Constants.js +3 -0
- package/esm/Core/Utils/EventListeners.js +19 -16
- package/esm/Core/Utils/ExternalInteractorBase.js +1 -1
- package/esm/Core/Utils/InteractionManager.js +17 -8
- package/esm/Core/Utils/ParticlesInteractorBase.js +1 -1
- package/esm/Core/Utils/QuadTree.js +5 -3
- package/esm/Core/Utils/Vector.js +7 -2
- package/esm/Core/Utils/Vector3d.js +14 -9
- package/esm/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
- package/esm/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
- package/esm/Options/Classes/ManualParticle.js +3 -2
- package/esm/Options/Classes/Options.js +3 -0
- package/esm/Utils/CanvasUtils.js +50 -40
- package/esm/Utils/ColorUtils.js +124 -45
- package/esm/Utils/EventDispatcher.js +6 -5
- package/esm/Utils/HslColorManager.js +5 -5
- package/esm/Utils/NumberUtils.js +35 -23
- package/esm/Utils/RgbColorManager.js +5 -5
- package/esm/Utils/Utils.js +102 -19
- package/package.json +1 -1
- package/report.html +3 -3
- package/tsparticles.engine.js +894 -5461
- package/tsparticles.engine.min.js +1 -1
- package/tsparticles.engine.min.js.LICENSE.txt +1 -1
- package/types/Core/Canvas.d.ts +5 -3
- package/types/Core/Container.d.ts +1 -1
- package/types/Core/Engine.d.ts +13 -8
- package/types/Core/Interfaces/IContainerPlugin.d.ts +3 -3
- package/types/Core/Interfaces/IEffectDrawer.d.ts +3 -3
- package/types/Core/Interfaces/IMovePathGenerator.d.ts +2 -2
- package/types/Core/Interfaces/IParticleHslAnimation.d.ts +4 -4
- package/types/Core/Interfaces/IParticleMover.d.ts +2 -2
- package/types/Core/Interfaces/IParticleUpdater.d.ts +2 -2
- package/types/Core/Interfaces/IParticleValueAnimation.d.ts +4 -0
- package/types/Core/Interfaces/IPlugin.d.ts +1 -1
- package/types/Core/Interfaces/IShapeDrawData.d.ts +2 -2
- package/types/Core/Interfaces/IShapeDrawer.d.ts +4 -4
- package/types/Core/Particle.d.ts +3 -3
- package/types/Core/Particles.d.ts +12 -8
- package/types/Core/Utils/Constants.d.ts +3 -0
- package/types/Core/Utils/ExternalInteractorBase.d.ts +1 -1
- package/types/Core/Utils/InteractionManager.d.ts +3 -3
- package/types/Core/Utils/ParticlesInteractorBase.d.ts +1 -1
- package/types/Core/Utils/Point.d.ts +1 -1
- package/types/Enums/Modes/OutMode.d.ts +0 -3
- package/types/Options/Classes/BackgroundMask/BackgroundMaskCover.d.ts +2 -1
- package/types/Options/Classes/Options.d.ts +1 -0
- package/types/Options/Classes/Particles/Move/Move.d.ts +1 -2
- package/types/Options/Classes/Particles/Move/OutModes.d.ts +5 -6
- package/types/Options/Interfaces/BackgroundMask/IBackgroundMask.d.ts +2 -1
- package/types/Options/Interfaces/BackgroundMask/IBackgroundMaskCover.d.ts +2 -1
- package/types/Options/Interfaces/IOptions.d.ts +1 -0
- package/types/Options/Interfaces/Interactivity/Modes/IModes.d.ts +1 -3
- package/types/Options/Interfaces/Particles/Move/IMove.d.ts +2 -2
- package/types/Options/Interfaces/Particles/Move/IOutModes.d.ts +6 -6
- package/types/Types/CustomEventArgs.d.ts +2 -2
- package/types/Types/ExportResult.d.ts +2 -2
- package/types/Types/ParticlesGroups.d.ts +1 -3
- package/types/Types/PathOptions.d.ts +1 -3
- package/types/Types/ShapeData.d.ts +1 -3
- package/types/Utils/CanvasUtils.d.ts +9 -8
- package/types/Utils/ColorUtils.d.ts +5 -0
- package/types/Utils/NumberUtils.d.ts +2 -2
- package/types/Utils/Utils.d.ts +9 -6
- package/umd/Core/Canvas.js +102 -49
- package/umd/Core/Container.js +54 -42
- package/umd/Core/Engine.js +72 -33
- package/umd/Core/Particle.js +46 -48
- package/umd/Core/Particles.js +95 -58
- package/umd/Core/Retina.js +5 -4
- package/umd/Core/Utils/Circle.js +4 -3
- package/umd/Core/Utils/Constants.js +4 -1
- package/umd/Core/Utils/EventListeners.js +18 -15
- package/umd/Core/Utils/ExternalInteractorBase.js +1 -1
- package/umd/Core/Utils/InteractionManager.js +17 -8
- package/umd/Core/Utils/ParticlesInteractorBase.js +1 -1
- package/umd/Core/Utils/QuadTree.js +5 -3
- package/umd/Core/Utils/Vector.js +7 -2
- package/umd/Core/Utils/Vector3d.js +14 -9
- package/umd/Options/Classes/BackgroundMask/BackgroundMask.js +1 -1
- package/umd/Options/Classes/BackgroundMask/BackgroundMaskCover.js +3 -2
- package/umd/Options/Classes/ManualParticle.js +3 -2
- package/umd/Options/Classes/Options.js +3 -0
- package/umd/Utils/CanvasUtils.js +50 -40
- package/umd/Utils/ColorUtils.js +127 -46
- package/umd/Utils/EventDispatcher.js +6 -5
- package/umd/Utils/HslColorManager.js +5 -5
- package/umd/Utils/NumberUtils.js +38 -25
- package/umd/Utils/RgbColorManager.js +5 -5
- package/umd/Utils/Utils.js +104 -20
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { OptionsColor } from "../OptionsColor.js";
|
|
2
2
|
export class BackgroundMaskCover {
|
|
3
3
|
constructor() {
|
|
4
|
-
this.color = new OptionsColor();
|
|
5
|
-
this.color.value = "#fff";
|
|
6
4
|
this.opacity = 1;
|
|
7
5
|
}
|
|
8
6
|
load(data) {
|
|
@@ -12,6 +10,9 @@ export class BackgroundMaskCover {
|
|
|
12
10
|
if (data.color !== undefined) {
|
|
13
11
|
this.color = OptionsColor.create(this.color, data.color);
|
|
14
12
|
}
|
|
13
|
+
if (data.image !== undefined) {
|
|
14
|
+
this.image = data.image;
|
|
15
|
+
}
|
|
15
16
|
if (data.opacity !== undefined) {
|
|
16
17
|
this.opacity = data.opacity;
|
|
17
18
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { deepExtend } from "../../Utils/Utils.js";
|
|
2
|
+
const defaultPosition = 50;
|
|
2
3
|
export class ManualParticle {
|
|
3
4
|
load(data) {
|
|
4
5
|
if (!data) {
|
|
@@ -6,8 +7,8 @@ export class ManualParticle {
|
|
|
6
7
|
}
|
|
7
8
|
if (data.position) {
|
|
8
9
|
this.position = {
|
|
9
|
-
x: data.position.x ??
|
|
10
|
-
y: data.position.y ??
|
|
10
|
+
x: data.position.x ?? defaultPosition,
|
|
11
|
+
y: data.position.y ?? defaultPosition,
|
|
11
12
|
mode: data.position.mode ?? "percent",
|
|
12
13
|
};
|
|
13
14
|
}
|
package/esm/Utils/CanvasUtils.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getStyleFromRgb } from "./ColorUtils.js";
|
|
2
|
+
const origin = { x: 0, y: 0 };
|
|
2
3
|
export function drawLine(context, begin, end) {
|
|
3
4
|
context.beginPath();
|
|
4
5
|
context.moveTo(begin.x, begin.y);
|
|
@@ -7,29 +8,28 @@ export function drawLine(context, begin, end) {
|
|
|
7
8
|
}
|
|
8
9
|
export function paintBase(context, dimension, baseColor) {
|
|
9
10
|
context.fillStyle = baseColor ?? "rgba(0,0,0,0)";
|
|
10
|
-
context.fillRect(
|
|
11
|
+
context.fillRect(origin.x, origin.y, dimension.width, dimension.height);
|
|
11
12
|
}
|
|
12
13
|
export function paintImage(context, dimension, image, opacity) {
|
|
13
14
|
if (!image) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
17
|
context.globalAlpha = opacity;
|
|
17
|
-
context.drawImage(image,
|
|
18
|
+
context.drawImage(image, origin.x, origin.y, dimension.width, dimension.height);
|
|
18
19
|
context.globalAlpha = 1;
|
|
19
20
|
}
|
|
20
21
|
export function clear(context, dimension) {
|
|
21
|
-
context.clearRect(
|
|
22
|
+
context.clearRect(origin.x, origin.y, dimension.width, dimension.height);
|
|
22
23
|
}
|
|
23
|
-
export function drawParticle(data) {
|
|
24
|
-
const { container, context, particle, delta, colorStyles, backgroundMask, composite, radius, opacity, shadow, transform, } = data
|
|
25
|
-
const pos = particle.getPosition(), angle = particle.rotation + (particle.pathRotation ? particle.velocity.angle : 0), rotateData = {
|
|
24
|
+
export async function drawParticle(data) {
|
|
25
|
+
const { container, context, particle, delta, colorStyles, backgroundMask, composite, radius, opacity, shadow, transform, } = data, pos = particle.getPosition(), defaultAngle = 0, angle = particle.rotation + (particle.pathRotation ? particle.velocity.angle : defaultAngle), rotateData = {
|
|
26
26
|
sin: Math.sin(angle),
|
|
27
27
|
cos: Math.cos(angle),
|
|
28
|
-
}, transformData = {
|
|
29
|
-
a: rotateData.cos * (transform.a ??
|
|
30
|
-
b: rotateData.sin * (transform.b ??
|
|
31
|
-
c: -rotateData.sin * (transform.c ??
|
|
32
|
-
d: rotateData.cos * (transform.d ??
|
|
28
|
+
}, defaultTransformFactor = 1, transformData = {
|
|
29
|
+
a: rotateData.cos * (transform.a ?? defaultTransformFactor),
|
|
30
|
+
b: rotateData.sin * (transform.b ?? defaultTransformFactor),
|
|
31
|
+
c: -rotateData.sin * (transform.c ?? defaultTransformFactor),
|
|
32
|
+
d: rotateData.cos * (transform.d ?? defaultTransformFactor),
|
|
33
33
|
};
|
|
34
34
|
context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, pos.x, pos.y);
|
|
35
35
|
if (backgroundMask) {
|
|
@@ -45,29 +45,28 @@ export function drawParticle(data) {
|
|
|
45
45
|
if (colorStyles.fill) {
|
|
46
46
|
context.fillStyle = colorStyles.fill;
|
|
47
47
|
}
|
|
48
|
-
const strokeWidth = particle.strokeWidth ??
|
|
48
|
+
const minStrokeWidth = 0, strokeWidth = particle.strokeWidth ?? minStrokeWidth;
|
|
49
49
|
context.lineWidth = strokeWidth;
|
|
50
50
|
if (colorStyles.stroke) {
|
|
51
51
|
context.strokeStyle = colorStyles.stroke;
|
|
52
52
|
}
|
|
53
|
-
const drawData = {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
drawEffect(drawData);
|
|
53
|
+
const drawData = {
|
|
54
|
+
container,
|
|
55
|
+
context,
|
|
56
|
+
particle,
|
|
57
|
+
radius,
|
|
58
|
+
opacity,
|
|
59
|
+
delta,
|
|
60
|
+
transformData,
|
|
61
|
+
strokeWidth,
|
|
62
|
+
};
|
|
63
|
+
await drawShape(drawData);
|
|
64
|
+
await drawShapeAfterDraw(drawData);
|
|
65
|
+
await drawEffect(drawData);
|
|
67
66
|
context.globalCompositeOperation = "source-over";
|
|
68
|
-
context.
|
|
67
|
+
context.resetTransform();
|
|
69
68
|
}
|
|
70
|
-
export function drawEffect(data) {
|
|
69
|
+
export async function drawEffect(data) {
|
|
71
70
|
const { container, context, particle, radius, opacity, delta, transformData } = data;
|
|
72
71
|
if (!particle.effect) {
|
|
73
72
|
return;
|
|
@@ -76,7 +75,7 @@ export function drawEffect(data) {
|
|
|
76
75
|
if (!drawer) {
|
|
77
76
|
return;
|
|
78
77
|
}
|
|
79
|
-
drawer.draw({
|
|
78
|
+
await drawer.draw({
|
|
80
79
|
context,
|
|
81
80
|
particle,
|
|
82
81
|
radius,
|
|
@@ -86,8 +85,8 @@ export function drawEffect(data) {
|
|
|
86
85
|
transformData: { ...transformData },
|
|
87
86
|
});
|
|
88
87
|
}
|
|
89
|
-
export function drawShape(data) {
|
|
90
|
-
const { container, context, particle, radius, opacity, delta, transformData } = data;
|
|
88
|
+
export async function drawShape(data) {
|
|
89
|
+
const { container, context, particle, radius, opacity, delta, strokeWidth, transformData } = data, minStrokeWidth = 0;
|
|
91
90
|
if (!particle.shape) {
|
|
92
91
|
return;
|
|
93
92
|
}
|
|
@@ -95,7 +94,8 @@ export function drawShape(data) {
|
|
|
95
94
|
if (!drawer) {
|
|
96
95
|
return;
|
|
97
96
|
}
|
|
98
|
-
|
|
97
|
+
context.beginPath();
|
|
98
|
+
await drawer.draw({
|
|
99
99
|
context,
|
|
100
100
|
particle,
|
|
101
101
|
radius,
|
|
@@ -104,17 +104,26 @@ export function drawShape(data) {
|
|
|
104
104
|
pixelRatio: container.retina.pixelRatio,
|
|
105
105
|
transformData: { ...transformData },
|
|
106
106
|
});
|
|
107
|
+
if (particle.shapeClose) {
|
|
108
|
+
context.closePath();
|
|
109
|
+
}
|
|
110
|
+
if (strokeWidth > minStrokeWidth) {
|
|
111
|
+
context.stroke();
|
|
112
|
+
}
|
|
113
|
+
if (particle.shapeFill) {
|
|
114
|
+
context.fill();
|
|
115
|
+
}
|
|
107
116
|
}
|
|
108
|
-
export function drawShapeAfterDraw(data) {
|
|
117
|
+
export async function drawShapeAfterDraw(data) {
|
|
109
118
|
const { container, context, particle, radius, opacity, delta, transformData } = data;
|
|
110
119
|
if (!particle.shape) {
|
|
111
120
|
return;
|
|
112
121
|
}
|
|
113
122
|
const drawer = container.shapeDrawers.get(particle.shape);
|
|
114
|
-
if (!drawer
|
|
123
|
+
if (!drawer?.afterDraw) {
|
|
115
124
|
return;
|
|
116
125
|
}
|
|
117
|
-
drawer.afterDraw({
|
|
126
|
+
await drawer.afterDraw({
|
|
118
127
|
context,
|
|
119
128
|
particle,
|
|
120
129
|
radius,
|
|
@@ -124,22 +133,23 @@ export function drawShapeAfterDraw(data) {
|
|
|
124
133
|
transformData: { ...transformData },
|
|
125
134
|
});
|
|
126
135
|
}
|
|
127
|
-
export function drawPlugin(context, plugin, delta) {
|
|
136
|
+
export async function drawPlugin(context, plugin, delta) {
|
|
128
137
|
if (!plugin.draw) {
|
|
129
138
|
return;
|
|
130
139
|
}
|
|
131
|
-
plugin.draw(context, delta);
|
|
140
|
+
await plugin.draw(context, delta);
|
|
132
141
|
}
|
|
133
|
-
export function drawParticlePlugin(context, plugin, particle, delta) {
|
|
142
|
+
export async function drawParticlePlugin(context, plugin, particle, delta) {
|
|
134
143
|
if (!plugin.drawParticle) {
|
|
135
144
|
return;
|
|
136
145
|
}
|
|
137
|
-
plugin.drawParticle(context, particle, delta);
|
|
146
|
+
await plugin.drawParticle(context, particle, delta);
|
|
138
147
|
}
|
|
139
148
|
export function alterHsl(color, type, value) {
|
|
149
|
+
const lFactor = 1;
|
|
140
150
|
return {
|
|
141
151
|
h: color.h,
|
|
142
152
|
s: color.s,
|
|
143
|
-
l: color.l + (type === "darken" ? -
|
|
153
|
+
l: color.l + (type === "darken" ? -lFactor : lFactor) * value,
|
|
144
154
|
};
|
|
145
155
|
}
|
package/esm/Utils/ColorUtils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { getRandom, getRangeValue, mix, randomInRange, setRangeValue } from "./NumberUtils.js";
|
|
1
|
+
import { clamp, getRandom, getRangeMax, getRangeMin, getRangeValue, mix, randomInRange, setRangeValue, } from "./NumberUtils.js";
|
|
2
2
|
import { isArray, isString, itemFromArray } from "./Utils.js";
|
|
3
|
+
import { millisecondsToSeconds, percentDenominator } from "../Core/Utils/Constants.js";
|
|
3
4
|
const randomColorValue = "random", midColorValue = "mid", colorManagers = new Map();
|
|
4
5
|
export function addColorManager(manager) {
|
|
5
6
|
colorManagers.set(manager.key, manager);
|
|
@@ -12,13 +13,15 @@ function stringToRgba(input) {
|
|
|
12
13
|
}
|
|
13
14
|
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i, hexFixed = input.replace(shorthandRegex, (_, r, g, b, a) => {
|
|
14
15
|
return r + r + g + g + b + b + (a !== undefined ? a + a : "");
|
|
15
|
-
}), regex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, result = regex.exec(hexFixed);
|
|
16
|
+
}), regex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i, result = regex.exec(hexFixed), radix = 16, defaultAlpha = 1, alphaFactor = 0xff;
|
|
16
17
|
return result
|
|
17
18
|
? {
|
|
18
|
-
a: result[4] !== undefined
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
a: result[4] !== undefined
|
|
20
|
+
? parseInt(result[4], radix) / alphaFactor
|
|
21
|
+
: defaultAlpha,
|
|
22
|
+
b: parseInt(result[3], radix),
|
|
23
|
+
g: parseInt(result[2], radix),
|
|
24
|
+
r: parseInt(result[1], radix),
|
|
22
25
|
}
|
|
23
26
|
: undefined;
|
|
24
27
|
}
|
|
@@ -71,26 +74,26 @@ export function rangeColorToHsl(color, index, useIndex = true) {
|
|
|
71
74
|
return rgb ? rgbToHsl(rgb) : undefined;
|
|
72
75
|
}
|
|
73
76
|
export function rgbToHsl(color) {
|
|
74
|
-
const r1 = color.r /
|
|
75
|
-
h:
|
|
76
|
-
l: (max + min) *
|
|
77
|
-
s:
|
|
77
|
+
const rgbMax = 255, hMax = 360, sMax = 100, lMax = 100, hMin = 0, sMin = 0, hPhase = 60, half = 0.5, double = 2, r1 = color.r / rgbMax, g1 = color.g / rgbMax, b1 = color.b / rgbMax, max = Math.max(r1, g1, b1), min = Math.min(r1, g1, b1), res = {
|
|
78
|
+
h: hMin,
|
|
79
|
+
l: (max + min) * half,
|
|
80
|
+
s: sMin,
|
|
78
81
|
};
|
|
79
82
|
if (max !== min) {
|
|
80
|
-
res.s = res.l <
|
|
83
|
+
res.s = res.l < half ? (max - min) / (max + min) : (max - min) / (double - max - min);
|
|
81
84
|
res.h =
|
|
82
85
|
r1 === max
|
|
83
86
|
? (g1 - b1) / (max - min)
|
|
84
|
-
: (res.h = g1 === max ?
|
|
87
|
+
: (res.h = g1 === max ? double + (b1 - r1) / (max - min) : double * double + (r1 - g1) / (max - min));
|
|
85
88
|
}
|
|
86
|
-
res.l *=
|
|
87
|
-
res.s *=
|
|
88
|
-
res.h *=
|
|
89
|
-
if (res.h <
|
|
90
|
-
res.h +=
|
|
89
|
+
res.l *= lMax;
|
|
90
|
+
res.s *= sMax;
|
|
91
|
+
res.h *= hPhase;
|
|
92
|
+
if (res.h < hMin) {
|
|
93
|
+
res.h += hMax;
|
|
91
94
|
}
|
|
92
|
-
if (res.h >=
|
|
93
|
-
res.h -=
|
|
95
|
+
if (res.h >= hMax) {
|
|
96
|
+
res.h -= hMax;
|
|
94
97
|
}
|
|
95
98
|
return res;
|
|
96
99
|
}
|
|
@@ -101,29 +104,33 @@ export function stringToRgb(input) {
|
|
|
101
104
|
return stringToRgba(input);
|
|
102
105
|
}
|
|
103
106
|
export function hslToRgb(hsl) {
|
|
104
|
-
const h = ((hsl.h %
|
|
105
|
-
if (s ===
|
|
106
|
-
const grayscaleValue = Math.round(lNormalized *
|
|
107
|
+
const hMax = 360, sMax = 100, lMax = 100, sMin = 0, lMin = 0, h = ((hsl.h % hMax) + hMax) % hMax, s = Math.max(sMin, Math.min(sMax, hsl.s)), l = Math.max(lMin, Math.min(lMax, hsl.l)), hNormalized = h / hMax, sNormalized = s / sMax, lNormalized = l / lMax, rgbFactor = 255, triple = 3;
|
|
108
|
+
if (s === sMin) {
|
|
109
|
+
const grayscaleValue = Math.round(lNormalized * rgbFactor);
|
|
107
110
|
return { r: grayscaleValue, g: grayscaleValue, b: grayscaleValue };
|
|
108
111
|
}
|
|
109
|
-
const channel = (temp1, temp2, temp3) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
+
const half = 0.5, double = 2, channel = (temp1, temp2, temp3) => {
|
|
113
|
+
const temp3Min = 0, temp3Max = 1, sextuple = 6;
|
|
114
|
+
if (temp3 < temp3Min) {
|
|
115
|
+
temp3++;
|
|
112
116
|
}
|
|
113
|
-
if (temp3 >
|
|
114
|
-
temp3
|
|
117
|
+
if (temp3 > temp3Max) {
|
|
118
|
+
temp3--;
|
|
115
119
|
}
|
|
116
|
-
if (temp3 *
|
|
117
|
-
return temp1 + (temp2 - temp1) *
|
|
120
|
+
if (temp3 * sextuple < temp3Max) {
|
|
121
|
+
return temp1 + (temp2 - temp1) * sextuple * temp3;
|
|
118
122
|
}
|
|
119
|
-
if (temp3 *
|
|
123
|
+
if (temp3 * double < temp3Max) {
|
|
120
124
|
return temp2;
|
|
121
125
|
}
|
|
122
|
-
if (temp3 *
|
|
123
|
-
|
|
126
|
+
if (temp3 * triple < temp3Max * double) {
|
|
127
|
+
const temp3Offset = double / triple;
|
|
128
|
+
return temp1 + (temp2 - temp1) * (temp3Offset - temp3) * sextuple;
|
|
124
129
|
}
|
|
125
130
|
return temp1;
|
|
126
|
-
},
|
|
131
|
+
}, sNormalizedOffset = 1, temp1 = lNormalized < half
|
|
132
|
+
? lNormalized * (sNormalizedOffset + sNormalized)
|
|
133
|
+
: lNormalized + sNormalized - lNormalized * sNormalized, temp2 = double * lNormalized - temp1, phaseNumerator = 1, phaseThird = phaseNumerator / triple, red = Math.min(rgbFactor, rgbFactor * channel(temp2, temp1, hNormalized + phaseThird)), green = Math.min(rgbFactor, rgbFactor * channel(temp2, temp1, hNormalized)), blue = Math.min(rgbFactor, rgbFactor * channel(temp2, temp1, hNormalized - phaseThird));
|
|
127
134
|
return { r: Math.round(red), g: Math.round(green), b: Math.round(blue) };
|
|
128
135
|
}
|
|
129
136
|
export function hslaToRgba(hsla) {
|
|
@@ -136,18 +143,20 @@ export function hslaToRgba(hsla) {
|
|
|
136
143
|
};
|
|
137
144
|
}
|
|
138
145
|
export function getRandomRgbColor(min) {
|
|
139
|
-
const fixedMin = min ??
|
|
146
|
+
const defaultMin = 0, fixedMin = min ?? defaultMin, rgbMax = 256;
|
|
140
147
|
return {
|
|
141
|
-
b: Math.floor(randomInRange(setRangeValue(fixedMin,
|
|
142
|
-
g: Math.floor(randomInRange(setRangeValue(fixedMin,
|
|
143
|
-
r: Math.floor(randomInRange(setRangeValue(fixedMin,
|
|
148
|
+
b: Math.floor(randomInRange(setRangeValue(fixedMin, rgbMax))),
|
|
149
|
+
g: Math.floor(randomInRange(setRangeValue(fixedMin, rgbMax))),
|
|
150
|
+
r: Math.floor(randomInRange(setRangeValue(fixedMin, rgbMax))),
|
|
144
151
|
};
|
|
145
152
|
}
|
|
146
153
|
export function getStyleFromRgb(color, opacity) {
|
|
147
|
-
|
|
154
|
+
const defaultOpacity = 1;
|
|
155
|
+
return `rgba(${color.r}, ${color.g}, ${color.b}, ${opacity ?? defaultOpacity})`;
|
|
148
156
|
}
|
|
149
157
|
export function getStyleFromHsl(color, opacity) {
|
|
150
|
-
|
|
158
|
+
const defaultOpacity = 1;
|
|
159
|
+
return `hsla(${color.h}, ${color.s}%, ${color.l}%, ${opacity ?? defaultOpacity})`;
|
|
151
160
|
}
|
|
152
161
|
export function colorMix(color1, color2, size1, size2) {
|
|
153
162
|
let rgb1 = color1, rgb2 = color2;
|
|
@@ -238,21 +247,91 @@ export function getHslAnimationFromHsl(hsl, animationOptions, reduceFactor) {
|
|
|
238
247
|
}
|
|
239
248
|
function setColorAnimation(colorValue, colorAnimation, reduceFactor) {
|
|
240
249
|
colorValue.enable = colorAnimation.enable;
|
|
250
|
+
const defaultVelocity = 0, decayOffset = 1, defaultLoops = 0, defaultTime = 0;
|
|
241
251
|
if (colorValue.enable) {
|
|
242
|
-
colorValue.velocity = (getRangeValue(colorAnimation.speed) /
|
|
243
|
-
colorValue.decay =
|
|
252
|
+
colorValue.velocity = (getRangeValue(colorAnimation.speed) / percentDenominator) * reduceFactor;
|
|
253
|
+
colorValue.decay = decayOffset - getRangeValue(colorAnimation.decay);
|
|
244
254
|
colorValue.status = "increasing";
|
|
245
|
-
colorValue.loops =
|
|
255
|
+
colorValue.loops = defaultLoops;
|
|
246
256
|
colorValue.maxLoops = getRangeValue(colorAnimation.count);
|
|
247
|
-
colorValue.time =
|
|
248
|
-
colorValue.delayTime = getRangeValue(colorAnimation.delay) *
|
|
257
|
+
colorValue.time = defaultTime;
|
|
258
|
+
colorValue.delayTime = getRangeValue(colorAnimation.delay) * millisecondsToSeconds;
|
|
249
259
|
if (!colorAnimation.sync) {
|
|
250
260
|
colorValue.velocity *= getRandom();
|
|
251
261
|
colorValue.value *= getRandom();
|
|
252
262
|
}
|
|
253
263
|
colorValue.initialValue = colorValue.value;
|
|
264
|
+
colorValue.offset = setRangeValue(colorAnimation.offset);
|
|
254
265
|
}
|
|
255
266
|
else {
|
|
256
|
-
colorValue.velocity =
|
|
267
|
+
colorValue.velocity = defaultVelocity;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
export function updateColorValue(data, range, decrease, delta) {
|
|
271
|
+
const minLoops = 0, minDelay = 0, identity = 1, minVelocity = 0, minOffset = 0, velocityFactor = 3.6;
|
|
272
|
+
if (!data ||
|
|
273
|
+
!data.enable ||
|
|
274
|
+
((data.maxLoops ?? minLoops) > minLoops && (data.loops ?? minLoops) > (data.maxLoops ?? minLoops))) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (!data.time) {
|
|
278
|
+
data.time = 0;
|
|
279
|
+
}
|
|
280
|
+
if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
|
|
281
|
+
data.time += delta.value;
|
|
282
|
+
}
|
|
283
|
+
if ((data.delayTime ?? minDelay) > minDelay && data.time < (data.delayTime ?? minDelay)) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const offset = data.offset ? randomInRange(data.offset) : minOffset, velocity = (data.velocity ?? minVelocity) * delta.factor + offset * velocityFactor, decay = data.decay ?? identity, max = getRangeMax(range), min = getRangeMin(range);
|
|
287
|
+
if (!decrease || data.status === "increasing") {
|
|
288
|
+
data.value += velocity;
|
|
289
|
+
if (data.value > max) {
|
|
290
|
+
if (!data.loops) {
|
|
291
|
+
data.loops = 0;
|
|
292
|
+
}
|
|
293
|
+
data.loops++;
|
|
294
|
+
if (decrease) {
|
|
295
|
+
data.status = "decreasing";
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
data.value -= max;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
data.value -= velocity;
|
|
304
|
+
const minValue = 0;
|
|
305
|
+
if (data.value < minValue) {
|
|
306
|
+
if (!data.loops) {
|
|
307
|
+
data.loops = 0;
|
|
308
|
+
}
|
|
309
|
+
data.loops++;
|
|
310
|
+
data.status = "increasing";
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (data.velocity && decay !== identity) {
|
|
314
|
+
data.velocity *= decay;
|
|
315
|
+
}
|
|
316
|
+
data.value = clamp(data.value, min, max);
|
|
317
|
+
}
|
|
318
|
+
export function updateColor(color, delta) {
|
|
319
|
+
if (!color) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const { h, s, l } = color;
|
|
323
|
+
const ranges = {
|
|
324
|
+
h: { min: 0, max: 360 },
|
|
325
|
+
s: { min: 0, max: 100 },
|
|
326
|
+
l: { min: 0, max: 100 },
|
|
327
|
+
};
|
|
328
|
+
if (h) {
|
|
329
|
+
updateColorValue(h, ranges.h, false, delta);
|
|
330
|
+
}
|
|
331
|
+
if (s) {
|
|
332
|
+
updateColorValue(s, ranges.s, true, delta);
|
|
333
|
+
}
|
|
334
|
+
if (l) {
|
|
335
|
+
updateColorValue(l, ranges.l, true, delta);
|
|
257
336
|
}
|
|
258
337
|
}
|
|
@@ -13,7 +13,7 @@ export class EventDispatcher {
|
|
|
13
13
|
}
|
|
14
14
|
dispatchEvent(type, args) {
|
|
15
15
|
const listeners = this._listeners.get(type);
|
|
16
|
-
listeners
|
|
16
|
+
listeners?.forEach((handler) => handler(args));
|
|
17
17
|
}
|
|
18
18
|
hasEventListener(type) {
|
|
19
19
|
return !!this._listeners.get(type);
|
|
@@ -31,15 +31,16 @@ export class EventDispatcher {
|
|
|
31
31
|
if (!arr) {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
|
-
const length = arr.length, idx = arr.indexOf(listener);
|
|
35
|
-
if (idx <
|
|
34
|
+
const length = arr.length, idx = arr.indexOf(listener), minIndex = 0;
|
|
35
|
+
if (idx < minIndex) {
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
const deleteCount = 1;
|
|
39
|
+
if (length === deleteCount) {
|
|
39
40
|
this._listeners.delete(type);
|
|
40
41
|
}
|
|
41
42
|
else {
|
|
42
|
-
arr.splice(idx,
|
|
43
|
+
arr.splice(idx, deleteCount);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -25,13 +25,13 @@ export class HslColorManager {
|
|
|
25
25
|
if (!input.startsWith("hsl")) {
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
|
-
const regex = /hsla?\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*(,\s*([\d.%]+)\s*)?\)/i, result = regex.exec(input);
|
|
28
|
+
const regex = /hsla?\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*(,\s*([\d.%]+)\s*)?\)/i, result = regex.exec(input), minLength = 4, defaultAlpha = 1, radix = 10;
|
|
29
29
|
return result
|
|
30
30
|
? hslaToRgba({
|
|
31
|
-
a: result.length >
|
|
32
|
-
h: parseInt(result[1],
|
|
33
|
-
l: parseInt(result[3],
|
|
34
|
-
s: parseInt(result[2],
|
|
31
|
+
a: result.length > minLength ? parseAlpha(result[5]) : defaultAlpha,
|
|
32
|
+
h: parseInt(result[1], radix),
|
|
33
|
+
l: parseInt(result[3], radix),
|
|
34
|
+
s: parseInt(result[2], radix),
|
|
35
35
|
})
|
|
36
36
|
: undefined;
|
|
37
37
|
}
|
package/esm/Utils/NumberUtils.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Vector } from "../Core/Utils/Vector.js";
|
|
2
2
|
import { isNumber } from "./Utils.js";
|
|
3
|
+
import { percentDenominator } from "../Core/Utils/Constants.js";
|
|
3
4
|
let _random = Math.random;
|
|
4
|
-
const easings = new Map();
|
|
5
|
+
const easings = new Map(), double = 2, doublePI = Math.PI * double;
|
|
5
6
|
export function addEasing(name, easing) {
|
|
6
7
|
if (easings.get(name)) {
|
|
7
8
|
return;
|
|
@@ -9,13 +10,14 @@ export function addEasing(name, easing) {
|
|
|
9
10
|
easings.set(name, easing);
|
|
10
11
|
}
|
|
11
12
|
export function getEasing(name) {
|
|
12
|
-
return easings.get(name)
|
|
13
|
+
return easings.get(name) ?? ((value) => value);
|
|
13
14
|
}
|
|
14
15
|
export function setRandom(rnd = Math.random) {
|
|
15
16
|
_random = rnd;
|
|
16
17
|
}
|
|
17
18
|
export function getRandom() {
|
|
18
|
-
|
|
19
|
+
const min = 0, max = 1;
|
|
20
|
+
return clamp(_random(), min, max - Number.EPSILON);
|
|
19
21
|
}
|
|
20
22
|
export function clamp(num, min, max) {
|
|
21
23
|
return Math.min(Math.max(num, min), max);
|
|
@@ -24,10 +26,10 @@ export function mix(comp1, comp2, weight1, weight2) {
|
|
|
24
26
|
return Math.floor((comp1 * weight1 + comp2 * weight2) / (weight1 + weight2));
|
|
25
27
|
}
|
|
26
28
|
export function randomInRange(r) {
|
|
27
|
-
const max = getRangeMax(r);
|
|
29
|
+
const max = getRangeMax(r), minOffset = 0;
|
|
28
30
|
let min = getRangeMin(r);
|
|
29
31
|
if (max === min) {
|
|
30
|
-
min =
|
|
32
|
+
min = minOffset;
|
|
31
33
|
}
|
|
32
34
|
return getRandom() * (max - min) + min;
|
|
33
35
|
}
|
|
@@ -53,39 +55,44 @@ export function setRangeValue(source, value) {
|
|
|
53
55
|
: setRangeValue(min, max);
|
|
54
56
|
}
|
|
55
57
|
export function getDistances(pointA, pointB) {
|
|
56
|
-
const dx = pointA.x - pointB.x, dy = pointA.y - pointB.y;
|
|
57
|
-
return { dx: dx, dy: dy, distance: Math.sqrt(dx **
|
|
58
|
+
const dx = pointA.x - pointB.x, dy = pointA.y - pointB.y, squareExp = 2;
|
|
59
|
+
return { dx: dx, dy: dy, distance: Math.sqrt(dx ** squareExp + dy ** squareExp) };
|
|
58
60
|
}
|
|
59
61
|
export function getDistance(pointA, pointB) {
|
|
60
62
|
return getDistances(pointA, pointB).distance;
|
|
61
63
|
}
|
|
64
|
+
export function degToRad(degrees) {
|
|
65
|
+
const PIDeg = 180;
|
|
66
|
+
return (degrees * Math.PI) / PIDeg;
|
|
67
|
+
}
|
|
62
68
|
export function getParticleDirectionAngle(direction, position, center) {
|
|
63
69
|
if (isNumber(direction)) {
|
|
64
|
-
return (direction
|
|
70
|
+
return degToRad(direction);
|
|
65
71
|
}
|
|
72
|
+
const empty = 0, half = 0.5, quarter = 0.25, threeQuarter = half + quarter;
|
|
66
73
|
switch (direction) {
|
|
67
74
|
case "top":
|
|
68
|
-
return -Math.PI *
|
|
75
|
+
return -Math.PI * half;
|
|
69
76
|
case "top-right":
|
|
70
|
-
return -Math.PI *
|
|
77
|
+
return -Math.PI * quarter;
|
|
71
78
|
case "right":
|
|
72
|
-
return
|
|
79
|
+
return empty;
|
|
73
80
|
case "bottom-right":
|
|
74
|
-
return Math.PI *
|
|
81
|
+
return Math.PI * quarter;
|
|
75
82
|
case "bottom":
|
|
76
|
-
return Math.PI *
|
|
83
|
+
return Math.PI * half;
|
|
77
84
|
case "bottom-left":
|
|
78
|
-
return Math.PI *
|
|
85
|
+
return Math.PI * threeQuarter;
|
|
79
86
|
case "left":
|
|
80
87
|
return Math.PI;
|
|
81
88
|
case "top-left":
|
|
82
|
-
return -Math.PI *
|
|
89
|
+
return -Math.PI * threeQuarter;
|
|
83
90
|
case "inside":
|
|
84
91
|
return Math.atan2(center.y - position.y, center.x - position.x);
|
|
85
92
|
case "outside":
|
|
86
93
|
return Math.atan2(position.y - center.y, position.x - center.x);
|
|
87
94
|
default:
|
|
88
|
-
return getRandom() *
|
|
95
|
+
return getRandom() * doublePI;
|
|
89
96
|
}
|
|
90
97
|
}
|
|
91
98
|
export function getParticleBaseVelocity(direction) {
|
|
@@ -95,20 +102,21 @@ export function getParticleBaseVelocity(direction) {
|
|
|
95
102
|
return baseVelocity;
|
|
96
103
|
}
|
|
97
104
|
export function collisionVelocity(v1, v2, m1, m2) {
|
|
98
|
-
|
|
105
|
+
const double = 2;
|
|
106
|
+
return Vector.create((v1.x * (m1 - m2)) / (m1 + m2) + (v2.x * double * m2) / (m1 + m2), v1.y);
|
|
99
107
|
}
|
|
100
108
|
export function calcPositionFromSize(data) {
|
|
101
|
-
return data.position
|
|
109
|
+
return data.position?.x !== undefined && data.position.y !== undefined
|
|
102
110
|
? {
|
|
103
|
-
x: (data.position.x * data.size.width) /
|
|
104
|
-
y: (data.position.y * data.size.height) /
|
|
111
|
+
x: (data.position.x * data.size.width) / percentDenominator,
|
|
112
|
+
y: (data.position.y * data.size.height) / percentDenominator,
|
|
105
113
|
}
|
|
106
114
|
: undefined;
|
|
107
115
|
}
|
|
108
116
|
export function calcPositionOrRandomFromSize(data) {
|
|
109
117
|
return {
|
|
110
|
-
x: ((data.position?.x ?? getRandom() *
|
|
111
|
-
y: ((data.position?.y ?? getRandom() *
|
|
118
|
+
x: ((data.position?.x ?? getRandom() * percentDenominator) * data.size.width) / percentDenominator,
|
|
119
|
+
y: ((data.position?.y ?? getRandom() * percentDenominator) * data.size.height) / percentDenominator,
|
|
112
120
|
};
|
|
113
121
|
}
|
|
114
122
|
export function calcPositionOrRandomFromSizeRanged(data) {
|
|
@@ -132,5 +140,9 @@ export function calcExactPositionOrRandomFromSizeRanged(data) {
|
|
|
132
140
|
return calcExactPositionOrRandomFromSize({ size: data.size, position });
|
|
133
141
|
}
|
|
134
142
|
export function parseAlpha(input) {
|
|
135
|
-
|
|
143
|
+
const defaultAlpha = 1;
|
|
144
|
+
if (!input) {
|
|
145
|
+
return defaultAlpha;
|
|
146
|
+
}
|
|
147
|
+
return input.endsWith("%") ? parseFloat(input) / percentDenominator : parseFloat(input);
|
|
136
148
|
}
|