@basmilius/sparkle 2.1.0 → 2.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/dist/index.d.mts +306 -459
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1106 -848
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -2
- package/src/aurora/index.ts +9 -3
- package/src/aurora/layer.ts +57 -29
- package/src/balloons/index.ts +9 -3
- package/src/balloons/layer.ts +50 -19
- package/src/bubbles/index.ts +9 -3
- package/src/bubbles/layer.ts +30 -17
- package/src/canvas.ts +12 -0
- package/src/color.ts +11 -2
- package/src/confetti/index.ts +15 -3
- package/src/confetti/layer.ts +8 -5
- package/src/confetti/particle.ts +12 -11
- package/src/donuts/consts.ts +2 -2
- package/src/donuts/index.ts +9 -3
- package/src/donuts/layer.ts +43 -12
- package/src/effect.ts +107 -0
- package/src/fade.ts +87 -0
- package/src/fireflies/index.ts +9 -3
- package/src/fireflies/layer.ts +26 -9
- package/src/fireflies/particle.ts +2 -2
- package/src/firepit/index.ts +9 -3
- package/src/firepit/layer.ts +26 -7
- package/src/fireworks/create-explosion.ts +237 -0
- package/src/fireworks/explosion.ts +1 -1
- package/src/fireworks/index.ts +15 -3
- package/src/fireworks/layer.ts +55 -304
- package/src/fireworks/spark.ts +2 -2
- package/src/fireworks/types.ts +2 -2
- package/src/glitter/index.ts +9 -4
- package/src/glitter/layer.ts +15 -7
- package/src/glitter/types.ts +10 -0
- package/src/index.ts +3 -4
- package/src/lanterns/index.ts +9 -4
- package/src/lanterns/layer.ts +22 -10
- package/src/lanterns/types.ts +8 -0
- package/src/layer.ts +13 -11
- package/src/leaves/index.ts +9 -4
- package/src/leaves/layer.ts +21 -14
- package/src/leaves/types.ts +9 -0
- package/src/lightning/index.ts +9 -4
- package/src/lightning/layer.ts +4 -4
- package/src/lightning/system.ts +3 -3
- package/src/lightning/types.ts +10 -2
- package/src/matrix/index.ts +9 -4
- package/src/matrix/layer.ts +15 -7
- package/src/matrix/types.ts +9 -0
- package/src/orbits/index.ts +9 -4
- package/src/orbits/layer.ts +51 -21
- package/src/orbits/types.ts +12 -1
- package/src/particles/index.ts +9 -3
- package/src/particles/layer.ts +55 -12
- package/src/petals/index.ts +9 -3
- package/src/petals/layer.ts +29 -13
- package/src/plasma/index.ts +9 -3
- package/src/plasma/layer.ts +21 -6
- package/src/rain/index.ts +9 -3
- package/src/rain/layer.ts +30 -8
- package/src/sandstorm/index.ts +9 -3
- package/src/sandstorm/layer.ts +26 -9
- package/src/scene.ts +201 -0
- package/src/shooting-stars/system.ts +26 -24
- package/src/shooting-stars/types.ts +2 -1
- package/src/simulation-canvas.ts +40 -4
- package/src/snow/index.ts +9 -3
- package/src/snow/layer.ts +24 -11
- package/src/sparklers/index.ts +13 -3
- package/src/sparklers/layer.ts +61 -15
- package/src/stars/index.ts +9 -3
- package/src/stars/layer.ts +28 -22
- package/src/streamers/index.ts +9 -3
- package/src/streamers/layer.ts +18 -6
- package/src/streamers/types.ts +1 -1
- package/src/waves/index.ts +9 -3
- package/src/waves/layer.ts +42 -45
- package/src/waves/types.ts +1 -0
- package/src/wormhole/index.ts +9 -3
- package/src/wormhole/layer.ts +22 -6
- package/src/aurora/simulation.ts +0 -19
- package/src/balloons/simulation.ts +0 -19
- package/src/bubbles/simulation.ts +0 -20
- package/src/confetti/simulation.ts +0 -27
- package/src/donuts/simulation.ts +0 -25
- package/src/fireflies/simulation.ts +0 -18
- package/src/firepit/simulation.ts +0 -17
- package/src/fireworks/simulation.ts +0 -18
- package/src/glitter/simulation.ts +0 -19
- package/src/lanterns/simulation.ts +0 -17
- package/src/layered.ts +0 -185
- package/src/leaves/simulation.ts +0 -18
- package/src/lightning/simulation.ts +0 -17
- package/src/matrix/simulation.ts +0 -18
- package/src/orbits/simulation.ts +0 -19
- package/src/particles/simulation.ts +0 -26
- package/src/petals/simulation.ts +0 -18
- package/src/plasma/simulation.ts +0 -17
- package/src/rain/simulation.ts +0 -21
- package/src/sandstorm/simulation.ts +0 -18
- package/src/snow/simulation.ts +0 -17
- package/src/sparklers/simulation.ts +0 -30
- package/src/stars/simulation.ts +0 -22
- package/src/streamers/simulation.ts +0 -16
- package/src/waves/simulation.ts +0 -18
- package/src/wormhole/simulation.ts +0 -17
package/src/layer.ts
CHANGED
|
@@ -7,18 +7,20 @@ export type EdgeFade = {
|
|
|
7
7
|
readonly right?: EdgeFadeSide;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Internal interface implemented by all Effect subclasses. Used by SimulationCanvas
|
|
12
|
+
* and Scene to drive rendering without depending on the generic Effect<TConfig> type.
|
|
13
|
+
*/
|
|
14
|
+
export interface SimulationLayer {
|
|
15
|
+
fade: EdgeFade | null;
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
abstract draw(ctx: CanvasRenderingContext2D, width: number, height: number): void;
|
|
17
|
+
tick(dt: number, width: number, height: number): void;
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
onMount(_canvas: HTMLCanvasElement): void {}
|
|
18
|
-
onUnmount(_canvas: HTMLCanvasElement): void {}
|
|
19
|
+
draw(ctx: CanvasRenderingContext2D, width: number, height: number): void;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
onResize(width: number, height: number): void;
|
|
22
|
+
|
|
23
|
+
onMount(canvas: HTMLCanvasElement): void;
|
|
24
|
+
|
|
25
|
+
onUnmount(canvas: HTMLCanvasElement): void;
|
|
24
26
|
}
|
package/src/leaves/index.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Leaves } from './layer';
|
|
2
|
+
import type { LeavesConfig } from './types';
|
|
3
|
+
import type { Effect } from '../effect';
|
|
4
|
+
|
|
5
|
+
export function createLeaves(config?: LeavesConfig): Effect<LeavesConfig> {
|
|
6
|
+
return new Leaves(config);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { LeavesConfig, Leaf } from './types';
|
package/src/leaves/layer.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Effect } from '../effect';
|
|
2
2
|
import { LEAF_COLORS, MULBERRY } from './consts';
|
|
3
|
-
import type {
|
|
4
|
-
import type { Leaf } from './types';
|
|
3
|
+
import type { Leaf, LeavesConfig } from './types';
|
|
5
4
|
|
|
6
|
-
export class
|
|
5
|
+
export class Leaves extends Effect<LeavesConfig> {
|
|
7
6
|
readonly #scale: number;
|
|
8
7
|
readonly #size: number;
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
#speed: number;
|
|
9
|
+
#wind: number;
|
|
11
10
|
readonly #colors: string[];
|
|
12
11
|
#maxCount: number;
|
|
13
12
|
#time: number = 0;
|
|
@@ -15,7 +14,7 @@ export class LeafLayer extends SimulationLayer {
|
|
|
15
14
|
#sprites: HTMLCanvasElement[] = [];
|
|
16
15
|
#height: number = 540;
|
|
17
16
|
|
|
18
|
-
constructor(config:
|
|
17
|
+
constructor(config: LeavesConfig = {}) {
|
|
19
18
|
super();
|
|
20
19
|
|
|
21
20
|
this.#scale = config.scale ?? 1;
|
|
@@ -40,6 +39,15 @@ export class LeafLayer extends SimulationLayer {
|
|
|
40
39
|
this.#height = height;
|
|
41
40
|
}
|
|
42
41
|
|
|
42
|
+
configure(config: Partial<LeavesConfig>): void {
|
|
43
|
+
if (config.speed !== undefined) {
|
|
44
|
+
this.#speed = config.speed;
|
|
45
|
+
}
|
|
46
|
+
if (config.wind !== undefined) {
|
|
47
|
+
this.#wind = config.wind;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
tick(dt: number, _width: number, height: number): void {
|
|
44
52
|
this.#height = height;
|
|
45
53
|
const speedFactor = (height / 540) / this.#speed;
|
|
@@ -47,8 +55,8 @@ export class LeafLayer extends SimulationLayer {
|
|
|
47
55
|
this.#time += 0.015 * dt;
|
|
48
56
|
|
|
49
57
|
const globalWind = Math.sin(this.#time * 0.5) * 0.4
|
|
50
|
-
|
|
51
|
-
|
|
58
|
+
+ Math.sin(this.#time * 1.3 + 2) * 0.2
|
|
59
|
+
+ Math.sin(this.#time * 3.1) * 0.1;
|
|
52
60
|
|
|
53
61
|
for (let index = 0; index < this.#leaves.length; index++) {
|
|
54
62
|
const leaf = this.#leaves[index];
|
|
@@ -87,11 +95,10 @@ export class LeafLayer extends SimulationLayer {
|
|
|
87
95
|
const py = leaf.y * height;
|
|
88
96
|
const displaySize = leaf.size * leaf.depth;
|
|
89
97
|
const scaleX = Math.cos(leaf.flipAngle);
|
|
98
|
+
const cos = Math.cos(leaf.rotation);
|
|
99
|
+
const sin = Math.sin(leaf.rotation);
|
|
90
100
|
|
|
91
|
-
ctx.
|
|
92
|
-
ctx.translate(px, py);
|
|
93
|
-
ctx.rotate(leaf.rotation);
|
|
94
|
-
ctx.scale(scaleX, 1);
|
|
101
|
+
ctx.setTransform(cos * scaleX, sin * scaleX, -sin, cos, px, py);
|
|
95
102
|
ctx.globalAlpha = 0.3 + leaf.depth * 0.7;
|
|
96
103
|
ctx.drawImage(
|
|
97
104
|
this.#sprites[leaf.colorIndex % this.#sprites.length],
|
|
@@ -100,9 +107,9 @@ export class LeafLayer extends SimulationLayer {
|
|
|
100
107
|
displaySize,
|
|
101
108
|
displaySize
|
|
102
109
|
);
|
|
103
|
-
ctx.restore();
|
|
104
110
|
}
|
|
105
111
|
|
|
112
|
+
ctx.resetTransform();
|
|
106
113
|
ctx.globalAlpha = 1;
|
|
107
114
|
}
|
|
108
115
|
|
package/src/leaves/types.ts
CHANGED
package/src/lightning/index.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Lightning } from './layer';
|
|
2
|
+
import type { LightningConfig } from './types';
|
|
3
|
+
import type { Effect } from '../effect';
|
|
4
|
+
|
|
5
|
+
export function createLightning(config?: LightningConfig): Effect<LightningConfig> {
|
|
6
|
+
return new Lightning(config);
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
export { LightningSystem } from './system';
|
|
5
10
|
export type { LightningSystemConfig } from './system';
|
|
6
|
-
export type { LightningBolt, LightningBranch } from './types';
|
|
11
|
+
export type { LightningConfig, LightningBolt, LightningBranch } from './types';
|
package/src/lightning/layer.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { hexToRGB } from '@basmilius/utils';
|
|
2
|
-
import {
|
|
2
|
+
import { Effect } from '../effect';
|
|
3
3
|
import { MULBERRY } from './consts';
|
|
4
|
-
import type {
|
|
4
|
+
import type { LightningConfig } from './types';
|
|
5
5
|
import { LightningSystem } from './system';
|
|
6
6
|
|
|
7
|
-
export class
|
|
7
|
+
export class Lightning extends Effect<LightningConfig> {
|
|
8
8
|
readonly #system: LightningSystem;
|
|
9
9
|
readonly #enableFlash: boolean;
|
|
10
10
|
|
|
11
|
-
constructor(config:
|
|
11
|
+
constructor(config: LightningConfig = {}) {
|
|
12
12
|
super();
|
|
13
13
|
|
|
14
14
|
this.#enableFlash = config.flash ?? true;
|
package/src/lightning/system.ts
CHANGED
|
@@ -101,7 +101,7 @@ export class LightningSystem {
|
|
|
101
101
|
ctx.globalCompositeOperation = 'source-over';
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
#drawSegments(ctx: CanvasRenderingContext2D, segments: {x: number; y: number}[], alpha: number, outerWidth: number, innerWidth: number, width: number, height: number): void {
|
|
104
|
+
#drawSegments(ctx: CanvasRenderingContext2D, segments: { x: number; y: number }[], alpha: number, outerWidth: number, innerWidth: number, width: number, height: number): void {
|
|
105
105
|
if (segments.length < 2) {
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
@@ -133,7 +133,7 @@ export class LightningSystem {
|
|
|
133
133
|
|
|
134
134
|
#createBolt(): LightningBolt {
|
|
135
135
|
const startX = 0.1 + this.#rng() * 0.8;
|
|
136
|
-
const segments: {x: number; y: number}[] = [{x: startX, y: 0}];
|
|
136
|
+
const segments: { x: number; y: number }[] = [{x: startX, y: 0}];
|
|
137
137
|
const branches: LightningBranch[] = [];
|
|
138
138
|
|
|
139
139
|
let currentX = startX;
|
|
@@ -165,7 +165,7 @@ export class LightningSystem {
|
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
#createBranch(startX: number, startY: number): LightningBranch {
|
|
168
|
-
const segments: {x: number; y: number}[] = [{x: startX, y: startY}];
|
|
168
|
+
const segments: { x: number; y: number }[] = [{x: startX, y: startY}];
|
|
169
169
|
const direction = this.#rng() > 0.5 ? 1 : -1;
|
|
170
170
|
const branchSteps = 3 + Math.floor(this.#rng() * 5);
|
|
171
171
|
|
package/src/lightning/types.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
export interface LightningConfig {
|
|
2
|
+
readonly frequency?: number;
|
|
3
|
+
readonly color?: string;
|
|
4
|
+
readonly branches?: boolean;
|
|
5
|
+
readonly flash?: boolean;
|
|
6
|
+
readonly scale?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
1
9
|
export type LightningBranch = {
|
|
2
|
-
segments: {x: number; y: number}[];
|
|
10
|
+
segments: { x: number; y: number }[];
|
|
3
11
|
alpha: number;
|
|
4
12
|
};
|
|
5
13
|
|
|
6
14
|
export type LightningBolt = {
|
|
7
|
-
segments: {x: number; y: number}[];
|
|
15
|
+
segments: { x: number; y: number }[];
|
|
8
16
|
branches: LightningBranch[];
|
|
9
17
|
alpha: number;
|
|
10
18
|
lifetime: number;
|
package/src/matrix/index.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Matrix } from './layer';
|
|
2
|
+
import type { MatrixConfig } from './types';
|
|
3
|
+
import type { Effect } from '../effect';
|
|
4
|
+
|
|
5
|
+
export function createMatrix(config?: MatrixConfig): Effect<MatrixConfig> {
|
|
6
|
+
return new Matrix(config);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { MatrixConfig, MatrixColumn } from './types';
|
package/src/matrix/layer.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { hexToRGB } from '@basmilius/utils';
|
|
2
|
-
import {
|
|
2
|
+
import { Effect } from '../effect';
|
|
3
3
|
import { MATRIX_CHARS, MULBERRY } from './consts';
|
|
4
|
-
import type {
|
|
5
|
-
import type { MatrixColumn } from './types';
|
|
4
|
+
import type { MatrixColumn, MatrixConfig } from './types';
|
|
6
5
|
|
|
7
|
-
export class
|
|
6
|
+
export class Matrix extends Effect<MatrixConfig> {
|
|
8
7
|
readonly #scale: number;
|
|
9
|
-
|
|
8
|
+
#speed: number;
|
|
10
9
|
readonly #fontSize: number;
|
|
11
|
-
|
|
10
|
+
#trailLength: number;
|
|
12
11
|
readonly #colorRGB: [number, number, number];
|
|
13
12
|
#maxColumns: number;
|
|
14
13
|
#columns: MatrixColumn[] = [];
|
|
@@ -17,7 +16,7 @@ export class MatrixLayer extends SimulationLayer {
|
|
|
17
16
|
#height: number = 540;
|
|
18
17
|
#initialized: boolean = false;
|
|
19
18
|
|
|
20
|
-
constructor(config:
|
|
19
|
+
constructor(config: MatrixConfig = {}) {
|
|
21
20
|
super();
|
|
22
21
|
|
|
23
22
|
this.#scale = config.scale ?? 1;
|
|
@@ -53,6 +52,15 @@ export class MatrixLayer extends SimulationLayer {
|
|
|
53
52
|
}
|
|
54
53
|
}
|
|
55
54
|
|
|
55
|
+
configure(config: Partial<MatrixConfig>): void {
|
|
56
|
+
if (config.speed !== undefined) {
|
|
57
|
+
this.#speed = config.speed;
|
|
58
|
+
}
|
|
59
|
+
if (config.trailLength !== undefined) {
|
|
60
|
+
this.#trailLength = config.trailLength;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
56
64
|
tick(dt: number, width: number, height: number): void {
|
|
57
65
|
this.#width = width;
|
|
58
66
|
this.#height = height;
|
package/src/matrix/types.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
export interface MatrixConfig {
|
|
2
|
+
readonly columns?: number;
|
|
3
|
+
readonly speed?: number;
|
|
4
|
+
readonly color?: string;
|
|
5
|
+
readonly fontSize?: number;
|
|
6
|
+
readonly trailLength?: number;
|
|
7
|
+
readonly scale?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
export type MatrixColumn = {
|
|
2
11
|
x: number;
|
|
3
12
|
y: number;
|
package/src/orbits/index.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Orbits } from './layer';
|
|
2
|
+
import type { OrbitsConfig } from './types';
|
|
3
|
+
import type { Effect } from '../effect';
|
|
4
|
+
|
|
5
|
+
export function createOrbits(config?: OrbitsConfig): Effect<OrbitsConfig> {
|
|
6
|
+
return new Orbits(config);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { OrbitsConfig, OrbitalCenter, Orbiter } from './types';
|
package/src/orbits/layer.ts
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { hexToRGB } from '@basmilius/utils';
|
|
2
|
-
import {
|
|
2
|
+
import { Effect } from '../effect';
|
|
3
3
|
import { MULBERRY, ORBIT_COLORS } from './consts';
|
|
4
|
-
import type {
|
|
5
|
-
import type { OrbitalCenter, Orbiter } from './types';
|
|
4
|
+
import type { OrbitalCenter, Orbiter, OrbitsConfig } from './types';
|
|
6
5
|
|
|
7
|
-
export class
|
|
6
|
+
export class Orbits extends Effect<OrbitsConfig> {
|
|
8
7
|
readonly #centerCount: number;
|
|
9
8
|
readonly #orbitersPerCenter: number;
|
|
10
|
-
|
|
9
|
+
#speed: number;
|
|
11
10
|
readonly #colors: string[];
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
#trailLength: number;
|
|
12
|
+
#showCenters: boolean;
|
|
13
|
+
#scale: number;
|
|
15
14
|
#centers: OrbitalCenter[] = [];
|
|
16
15
|
#orbiters: Orbiter[] = [];
|
|
17
16
|
#time: number = 0;
|
|
18
17
|
#initialized: boolean = false;
|
|
19
18
|
|
|
20
|
-
constructor(config:
|
|
19
|
+
constructor(config: OrbitsConfig = {}) {
|
|
21
20
|
super();
|
|
22
21
|
|
|
23
22
|
this.#centerCount = config.centers ?? 3;
|
|
@@ -54,6 +53,21 @@ export class OrbitLayer extends SimulationLayer {
|
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
|
|
56
|
+
configure(config: Partial<OrbitsConfig>): void {
|
|
57
|
+
if (config.speed !== undefined) {
|
|
58
|
+
this.#speed = config.speed;
|
|
59
|
+
}
|
|
60
|
+
if (config.trailLength !== undefined) {
|
|
61
|
+
this.#trailLength = config.trailLength;
|
|
62
|
+
}
|
|
63
|
+
if (config.showCenters !== undefined) {
|
|
64
|
+
this.#showCenters = config.showCenters;
|
|
65
|
+
}
|
|
66
|
+
if (config.scale !== undefined) {
|
|
67
|
+
this.#scale = config.scale;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
57
71
|
tick(dt: number, width: number, height: number): void {
|
|
58
72
|
this.#time += 0.01 * dt * this.#speed;
|
|
59
73
|
|
|
@@ -77,10 +91,17 @@ export class OrbitLayer extends SimulationLayer {
|
|
|
77
91
|
const px = cx + rotatedX;
|
|
78
92
|
const py = cy + rotatedY;
|
|
79
93
|
|
|
80
|
-
orbiter.trail
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
const trail = orbiter.trail;
|
|
95
|
+
const maxLen = this.#trailLength;
|
|
96
|
+
|
|
97
|
+
if (trail.length < maxLen) {
|
|
98
|
+
trail.push({x: px, y: py});
|
|
99
|
+
orbiter.trailHead = trail.length - 1;
|
|
100
|
+
} else {
|
|
101
|
+
const next = (orbiter.trailHead + 1) % maxLen;
|
|
102
|
+
trail[next].x = px;
|
|
103
|
+
trail[next].y = py;
|
|
104
|
+
orbiter.trailHead = next;
|
|
84
105
|
}
|
|
85
106
|
}
|
|
86
107
|
}
|
|
@@ -114,10 +135,15 @@ export class OrbitLayer extends SimulationLayer {
|
|
|
114
135
|
|
|
115
136
|
for (const orbiter of this.#orbiters) {
|
|
116
137
|
const [cr, cg, cb] = hexToRGB(orbiter.color);
|
|
138
|
+
const trail = orbiter.trail;
|
|
139
|
+
const trailLen = trail.length;
|
|
117
140
|
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
141
|
+
if (trailLen > 1) {
|
|
142
|
+
const isFull = trailLen === this.#trailLength;
|
|
143
|
+
const oldest = isFull ? (orbiter.trailHead + 1) % trailLen : 0;
|
|
144
|
+
|
|
145
|
+
for (let ti = 0; ti < trailLen - 1; ti++) {
|
|
146
|
+
const progress = (ti + 1) / trailLen;
|
|
121
147
|
const trailAlpha = progress * 0.5;
|
|
122
148
|
const trailWidth = orbiter.size * progress * this.#scale;
|
|
123
149
|
|
|
@@ -125,18 +151,21 @@ export class OrbitLayer extends SimulationLayer {
|
|
|
125
151
|
continue;
|
|
126
152
|
}
|
|
127
153
|
|
|
154
|
+
const idx0 = (oldest + ti) % trailLen;
|
|
155
|
+
const idx1 = (oldest + ti + 1) % trailLen;
|
|
156
|
+
|
|
128
157
|
ctx.globalAlpha = trailAlpha;
|
|
129
158
|
ctx.strokeStyle = `rgb(${cr}, ${cg}, ${cb})`;
|
|
130
159
|
ctx.lineWidth = trailWidth;
|
|
131
160
|
ctx.beginPath();
|
|
132
|
-
ctx.moveTo(
|
|
133
|
-
ctx.lineTo(
|
|
161
|
+
ctx.moveTo(trail[idx0].x, trail[idx0].y);
|
|
162
|
+
ctx.lineTo(trail[idx1].x, trail[idx1].y);
|
|
134
163
|
ctx.stroke();
|
|
135
164
|
}
|
|
136
165
|
}
|
|
137
166
|
|
|
138
|
-
if (
|
|
139
|
-
const head =
|
|
167
|
+
if (trailLen > 0) {
|
|
168
|
+
const head = trail[orbiter.trailHead];
|
|
140
169
|
const headSize = orbiter.size * this.#scale;
|
|
141
170
|
|
|
142
171
|
const glow = ctx.createRadialGradient(
|
|
@@ -177,7 +206,8 @@ export class OrbitLayer extends SimulationLayer {
|
|
|
177
206
|
tilt: MULBERRY.next() * Math.PI,
|
|
178
207
|
size: 1.5 + MULBERRY.next() * 2.5,
|
|
179
208
|
color: this.#colors[Math.floor(MULBERRY.next() * this.#colors.length)],
|
|
180
|
-
trail: []
|
|
209
|
+
trail: [],
|
|
210
|
+
trailHead: 0
|
|
181
211
|
};
|
|
182
212
|
}
|
|
183
213
|
}
|
package/src/orbits/types.ts
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
export interface OrbitsConfig {
|
|
2
|
+
readonly centers?: number;
|
|
3
|
+
readonly orbitersPerCenter?: number;
|
|
4
|
+
readonly speed?: number;
|
|
5
|
+
readonly colors?: string[];
|
|
6
|
+
readonly trailLength?: number;
|
|
7
|
+
readonly showCenters?: boolean;
|
|
8
|
+
readonly scale?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
export type OrbitalCenter = {
|
|
2
12
|
x: number;
|
|
3
13
|
y: number;
|
|
@@ -12,5 +22,6 @@ export type Orbiter = {
|
|
|
12
22
|
tilt: number;
|
|
13
23
|
size: number;
|
|
14
24
|
color: string;
|
|
15
|
-
trail: {x: number; y: number}[];
|
|
25
|
+
trail: { x: number; y: number }[];
|
|
26
|
+
trailHead: number;
|
|
16
27
|
};
|
package/src/particles/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Particles } from './layer';
|
|
2
|
+
import type { ParticlesConfig } from './layer';
|
|
3
|
+
import type { Effect } from '../effect';
|
|
4
|
+
|
|
5
|
+
export function createParticles(config?: ParticlesConfig): Effect<ParticlesConfig> {
|
|
6
|
+
return new Particles(config);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { ParticlesConfig };
|
|
4
10
|
export type { NetworkParticle, ParticleMouseMode } from './types';
|
package/src/particles/layer.ts
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
import { hexToRGB } from '@basmilius/utils';
|
|
2
|
-
import {
|
|
2
|
+
import { Effect } from '../effect';
|
|
3
3
|
import { MULBERRY } from './consts';
|
|
4
|
-
import type { ParticleSimulationConfig } from './simulation';
|
|
5
4
|
import type { NetworkParticle, ParticleMouseMode } from './types';
|
|
6
5
|
|
|
7
|
-
export
|
|
8
|
-
readonly
|
|
9
|
-
readonly
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
12
|
-
readonly
|
|
13
|
-
readonly
|
|
14
|
-
readonly
|
|
15
|
-
readonly
|
|
6
|
+
export interface ParticlesConfig {
|
|
7
|
+
readonly count?: number;
|
|
8
|
+
readonly color?: string;
|
|
9
|
+
readonly lineColor?: string;
|
|
10
|
+
readonly size?: [number, number];
|
|
11
|
+
readonly speed?: [number, number];
|
|
12
|
+
readonly connectionDistance?: number;
|
|
13
|
+
readonly lineWidth?: number;
|
|
14
|
+
readonly mouseMode?: ParticleMouseMode;
|
|
15
|
+
readonly mouseRadius?: number;
|
|
16
|
+
readonly mouseStrength?: number;
|
|
17
|
+
readonly particleForces?: boolean;
|
|
18
|
+
readonly glow?: boolean;
|
|
19
|
+
readonly background?: string | null;
|
|
20
|
+
readonly scale?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class Particles extends Effect<ParticlesConfig> {
|
|
24
|
+
#scale: number;
|
|
25
|
+
#connectionDistance: number;
|
|
26
|
+
#lineWidth: number;
|
|
27
|
+
#mouseMode: ParticleMouseMode;
|
|
28
|
+
#mouseRadius: number;
|
|
29
|
+
#mouseStrength: number;
|
|
30
|
+
#particleForces: boolean;
|
|
31
|
+
#glow: boolean;
|
|
16
32
|
readonly #background: string | null;
|
|
17
33
|
readonly #colorRGB: [number, number, number];
|
|
18
34
|
readonly #lineColorRGB: [number, number, number];
|
|
@@ -31,7 +47,7 @@ export class ParticleLayer extends SimulationLayer {
|
|
|
31
47
|
#height: number = 540;
|
|
32
48
|
#initialized: boolean = false;
|
|
33
49
|
|
|
34
|
-
constructor(config:
|
|
50
|
+
constructor(config: ParticlesConfig = {}) {
|
|
35
51
|
super();
|
|
36
52
|
|
|
37
53
|
this.#scale = config.scale ?? 1;
|
|
@@ -60,6 +76,33 @@ export class ParticleLayer extends SimulationLayer {
|
|
|
60
76
|
this.#onMouseLeaveBound = this.#onMouseLeave.bind(this);
|
|
61
77
|
}
|
|
62
78
|
|
|
79
|
+
configure(config: Partial<ParticlesConfig>): void {
|
|
80
|
+
if (config.scale !== undefined) {
|
|
81
|
+
this.#scale = config.scale;
|
|
82
|
+
}
|
|
83
|
+
if (config.connectionDistance !== undefined) {
|
|
84
|
+
this.#connectionDistance = config.connectionDistance * this.#scale;
|
|
85
|
+
}
|
|
86
|
+
if (config.lineWidth !== undefined) {
|
|
87
|
+
this.#lineWidth = config.lineWidth;
|
|
88
|
+
}
|
|
89
|
+
if (config.mouseMode !== undefined) {
|
|
90
|
+
this.#mouseMode = config.mouseMode;
|
|
91
|
+
}
|
|
92
|
+
if (config.mouseRadius !== undefined) {
|
|
93
|
+
this.#mouseRadius = config.mouseRadius * this.#scale;
|
|
94
|
+
}
|
|
95
|
+
if (config.mouseStrength !== undefined) {
|
|
96
|
+
this.#mouseStrength = config.mouseStrength;
|
|
97
|
+
}
|
|
98
|
+
if (config.particleForces !== undefined) {
|
|
99
|
+
this.#particleForces = config.particleForces;
|
|
100
|
+
}
|
|
101
|
+
if (config.glow !== undefined) {
|
|
102
|
+
this.#glow = config.glow;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
63
106
|
onResize(width: number, height: number): void {
|
|
64
107
|
this.#width = width;
|
|
65
108
|
this.#height = height;
|
package/src/petals/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Petals } from './layer';
|
|
2
|
+
import type { PetalsConfig } from './layer';
|
|
3
|
+
import type { Effect } from '../effect';
|
|
4
|
+
|
|
5
|
+
export function createPetals(config?: PetalsConfig): Effect<PetalsConfig> {
|
|
6
|
+
return new Petals(config);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type { PetalsConfig };
|
|
4
10
|
export type { Petal } from './types';
|