@basmilius/sparkle 2.1.0 → 2.3.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 (108) hide show
  1. package/dist/index.d.mts +317 -459
  2. package/dist/index.d.mts.map +1 -1
  3. package/dist/index.mjs +1258 -949
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +6 -2
  6. package/src/aurora/index.ts +9 -3
  7. package/src/aurora/layer.ts +57 -29
  8. package/src/balloons/index.ts +9 -3
  9. package/src/balloons/layer.ts +50 -19
  10. package/src/bubbles/index.ts +9 -3
  11. package/src/bubbles/layer.ts +30 -17
  12. package/src/canvas.ts +92 -2
  13. package/src/color.ts +11 -2
  14. package/src/confetti/index.ts +15 -3
  15. package/src/confetti/layer.ts +8 -5
  16. package/src/confetti/particle.ts +12 -11
  17. package/src/confetti/shapes.ts +84 -97
  18. package/src/donuts/consts.ts +2 -2
  19. package/src/donuts/index.ts +9 -3
  20. package/src/donuts/layer.ts +43 -12
  21. package/src/effect.ts +107 -0
  22. package/src/fade.ts +87 -0
  23. package/src/fireflies/index.ts +9 -3
  24. package/src/fireflies/layer.ts +26 -9
  25. package/src/fireflies/particle.ts +2 -2
  26. package/src/firepit/index.ts +9 -3
  27. package/src/firepit/layer.ts +26 -7
  28. package/src/fireworks/create-explosion.ts +237 -0
  29. package/src/fireworks/explosion.ts +1 -1
  30. package/src/fireworks/index.ts +15 -3
  31. package/src/fireworks/layer.ts +55 -304
  32. package/src/fireworks/spark.ts +2 -2
  33. package/src/fireworks/types.ts +2 -2
  34. package/src/glitter/index.ts +9 -4
  35. package/src/glitter/layer.ts +15 -7
  36. package/src/glitter/types.ts +10 -0
  37. package/src/index.ts +3 -4
  38. package/src/lanterns/index.ts +9 -4
  39. package/src/lanterns/layer.ts +22 -10
  40. package/src/lanterns/types.ts +8 -0
  41. package/src/layer.ts +13 -11
  42. package/src/leaves/index.ts +9 -4
  43. package/src/leaves/layer.ts +21 -14
  44. package/src/leaves/types.ts +9 -0
  45. package/src/lightning/index.ts +9 -4
  46. package/src/lightning/layer.ts +4 -4
  47. package/src/lightning/system.ts +3 -3
  48. package/src/lightning/types.ts +10 -2
  49. package/src/matrix/index.ts +9 -4
  50. package/src/matrix/layer.ts +15 -7
  51. package/src/matrix/types.ts +9 -0
  52. package/src/orbits/index.ts +9 -4
  53. package/src/orbits/layer.ts +51 -21
  54. package/src/orbits/types.ts +12 -1
  55. package/src/particles/index.ts +9 -3
  56. package/src/particles/layer.ts +55 -12
  57. package/src/petals/index.ts +9 -3
  58. package/src/petals/layer.ts +29 -13
  59. package/src/plasma/index.ts +9 -3
  60. package/src/plasma/layer.ts +21 -6
  61. package/src/rain/index.ts +9 -3
  62. package/src/rain/layer.ts +30 -8
  63. package/src/sandstorm/index.ts +9 -3
  64. package/src/sandstorm/layer.ts +26 -9
  65. package/src/scene.ts +204 -0
  66. package/src/shooting-stars/system.ts +26 -24
  67. package/src/shooting-stars/types.ts +2 -1
  68. package/src/simulation-canvas.ts +45 -6
  69. package/src/snow/index.ts +9 -3
  70. package/src/snow/layer.ts +24 -11
  71. package/src/sparklers/index.ts +13 -3
  72. package/src/sparklers/layer.ts +61 -15
  73. package/src/stars/index.ts +9 -3
  74. package/src/stars/layer.ts +28 -22
  75. package/src/streamers/index.ts +9 -3
  76. package/src/streamers/layer.ts +18 -6
  77. package/src/streamers/types.ts +1 -1
  78. package/src/waves/index.ts +9 -3
  79. package/src/waves/layer.ts +42 -45
  80. package/src/waves/types.ts +1 -0
  81. package/src/wormhole/index.ts +9 -3
  82. package/src/wormhole/layer.ts +22 -6
  83. package/src/aurora/simulation.ts +0 -19
  84. package/src/balloons/simulation.ts +0 -19
  85. package/src/bubbles/simulation.ts +0 -20
  86. package/src/confetti/simulation.ts +0 -27
  87. package/src/donuts/simulation.ts +0 -25
  88. package/src/fireflies/simulation.ts +0 -18
  89. package/src/firepit/simulation.ts +0 -17
  90. package/src/fireworks/simulation.ts +0 -18
  91. package/src/glitter/simulation.ts +0 -19
  92. package/src/lanterns/simulation.ts +0 -17
  93. package/src/layered.ts +0 -185
  94. package/src/leaves/simulation.ts +0 -18
  95. package/src/lightning/simulation.ts +0 -17
  96. package/src/matrix/simulation.ts +0 -18
  97. package/src/orbits/simulation.ts +0 -19
  98. package/src/particles/simulation.ts +0 -26
  99. package/src/petals/simulation.ts +0 -18
  100. package/src/plasma/simulation.ts +0 -17
  101. package/src/rain/simulation.ts +0 -21
  102. package/src/sandstorm/simulation.ts +0 -18
  103. package/src/snow/simulation.ts +0 -17
  104. package/src/sparklers/simulation.ts +0 -30
  105. package/src/stars/simulation.ts +0 -22
  106. package/src/streamers/simulation.ts +0 -16
  107. package/src/waves/simulation.ts +0 -18
  108. package/src/wormhole/simulation.ts +0 -17
@@ -1,30 +1,38 @@
1
- import { SimulationLayer } from '../layer';
1
+ import { hexToRGB } from '@basmilius/utils';
2
+ import { Effect } from '../effect';
2
3
  import { MULBERRY } from './consts';
3
- import type { WaveSimulationConfig } from './simulation';
4
4
  import type { Wave } from './types';
5
5
 
6
6
  const DEFAULT_COLORS = ['#0a3d6b', '#0e5a8a', '#1a7ab5', '#3399cc', '#66c2e0'];
7
7
 
8
- export class WaveLayer extends SimulationLayer {
9
- readonly #speed: number;
10
- readonly #foamColor: string;
11
- readonly #foamAmount: number;
12
- readonly #scale: number;
13
- #time: number = 0;
8
+ export interface WavesConfig {
9
+ readonly layers?: number;
10
+ readonly speed?: number;
11
+ readonly colors?: string[];
12
+ readonly foamColor?: string;
13
+ readonly foamAmount?: number;
14
+ readonly scale?: number;
15
+ }
16
+
17
+ export class Waves extends Effect<WavesConfig> {
18
+ #speed: number;
19
+ #foamAmount: number;
20
+ #scale: number;
21
+ readonly #foamRGB: [number, number, number];
14
22
  #waves: Wave[] = [];
15
- #foamParticles: {x: number; y: number; alpha: number; size: number}[] = [];
23
+ #foamParticles: { x: number; y: number; alpha: number; size: number }[] = [];
16
24
  #maxFoamParticles: number;
17
25
 
18
- constructor(config: WaveSimulationConfig = {}) {
26
+ constructor(config: WavesConfig = {}) {
19
27
  super();
20
28
 
21
29
  const layers = config.layers ?? 5;
22
30
  const colors = config.colors ?? DEFAULT_COLORS;
23
31
  this.#speed = config.speed ?? 1;
24
- this.#foamColor = config.foamColor ?? '#ffffff';
25
32
  this.#foamAmount = config.foamAmount ?? 0.4;
26
33
  this.#scale = config.scale ?? 1;
27
34
  this.#maxFoamParticles = 120;
35
+ this.#foamRGB = hexToRGB(config.foamColor ?? '#ffffff');
28
36
 
29
37
  if (innerWidth < 991) {
30
38
  this.#maxFoamParticles = Math.floor(this.#maxFoamParticles / 2);
@@ -37,20 +45,31 @@ export class WaveLayer extends SimulationLayer {
37
45
  this.#waves.push({
38
46
  amplitude: (20 + MULBERRY.next() * 30) * (1 - depth * 0.4),
39
47
  frequency: 0.005 + MULBERRY.next() * 0.008 + depth * 0.002,
40
- speed: (0.4 + MULBERRY.next() * 0.6 + depth * 0.3) * this.#speed,
48
+ speed: 0.4 + MULBERRY.next() * 0.6 + depth * 0.3,
41
49
  phase: MULBERRY.next() * Math.PI * 2,
42
50
  baseY: 0.35 + depth * 0.13,
43
51
  color,
44
- foamThreshold: 0.6 + MULBERRY.next() * 0.3
52
+ foamThreshold: 0.6 + MULBERRY.next() * 0.3,
53
+ rgb: hexToRGB(color)
45
54
  });
46
55
  }
47
56
  }
48
57
 
49
- tick(dt: number, width: number, height: number): void {
50
- this.#time += 0.02 * dt * this.#speed;
58
+ configure(config: Partial<WavesConfig>): void {
59
+ if (config.speed !== undefined) {
60
+ this.#speed = config.speed;
61
+ }
62
+ if (config.foamAmount !== undefined) {
63
+ this.#foamAmount = config.foamAmount;
64
+ }
65
+ if (config.scale !== undefined) {
66
+ this.#scale = config.scale;
67
+ }
68
+ }
51
69
 
70
+ tick(dt: number, width: number, height: number): void {
52
71
  for (const wave of this.#waves) {
53
- wave.phase += 0.015 * wave.speed * dt;
72
+ wave.phase += 0.015 * wave.speed * this.#speed * dt;
54
73
  }
55
74
 
56
75
  let aliveFoam = 0;
@@ -100,6 +119,7 @@ export class WaveLayer extends SimulationLayer {
100
119
 
101
120
  for (let wi = 0; wi < this.#waves.length; wi++) {
102
121
  const wave = this.#waves[wi];
122
+ const [wr, wg, wb] = wave.rgb;
103
123
  const centerY = wave.baseY * height;
104
124
 
105
125
  ctx.beginPath();
@@ -118,15 +138,17 @@ export class WaveLayer extends SimulationLayer {
118
138
  ctx.closePath();
119
139
 
120
140
  const gradient = ctx.createLinearGradient(0, centerY - wave.amplitude * this.#scale, 0, height);
121
- gradient.addColorStop(0, this.#adjustAlpha(wave.color, 0.85));
122
- gradient.addColorStop(0.4, wave.color);
123
- gradient.addColorStop(1, this.#darkenColor(wave.color, 0.6));
141
+ gradient.addColorStop(0, `rgba(${wr}, ${wg}, ${wb}, 0.85)`);
142
+ gradient.addColorStop(0.4, `rgb(${wr}, ${wg}, ${wb})`);
143
+ gradient.addColorStop(1, `rgb(${Math.floor(wr * 0.6)}, ${Math.floor(wg * 0.6)}, ${Math.floor(wb * 0.6)})`);
124
144
 
125
145
  ctx.fillStyle = gradient;
126
146
  ctx.fill();
127
147
  }
128
148
 
129
149
  if (this.#foamAmount > 0) {
150
+ const [fr, fg, fb] = this.#foamRGB;
151
+
130
152
  for (const foam of this.#foamParticles) {
131
153
  if (foam.alpha <= 0) {
132
154
  continue;
@@ -134,34 +156,9 @@ export class WaveLayer extends SimulationLayer {
134
156
 
135
157
  ctx.beginPath();
136
158
  ctx.arc(foam.x, foam.y, foam.size * this.#scale, 0, Math.PI * 2);
137
- ctx.fillStyle = this.#adjustAlpha(this.#foamColor, foam.alpha * this.#foamAmount);
159
+ ctx.fillStyle = `rgba(${fr}, ${fg}, ${fb}, ${foam.alpha * this.#foamAmount})`;
138
160
  ctx.fill();
139
161
  }
140
162
  }
141
163
  }
142
-
143
- #adjustAlpha(color: string, alpha: number): string {
144
- const canvas = document.createElement('canvas');
145
- canvas.width = 1;
146
- canvas.height = 1;
147
- const ctx = canvas.getContext('2d')!;
148
- ctx.fillStyle = color;
149
- ctx.fillRect(0, 0, 1, 1);
150
- const data = ctx.getImageData(0, 0, 1, 1).data;
151
- return `rgba(${data[0]}, ${data[1]}, ${data[2]}, ${alpha})`;
152
- }
153
-
154
- #darkenColor(color: string, factor: number): string {
155
- const canvas = document.createElement('canvas');
156
- canvas.width = 1;
157
- canvas.height = 1;
158
- const ctx = canvas.getContext('2d')!;
159
- ctx.fillStyle = color;
160
- ctx.fillRect(0, 0, 1, 1);
161
- const data = ctx.getImageData(0, 0, 1, 1).data;
162
- const r = Math.floor(data[0] * factor);
163
- const g = Math.floor(data[1] * factor);
164
- const b = Math.floor(data[2] * factor);
165
- return `rgb(${r}, ${g}, ${b})`;
166
- }
167
164
  }
@@ -6,4 +6,5 @@ export type Wave = {
6
6
  baseY: number;
7
7
  color: string;
8
8
  foamThreshold: number;
9
+ rgb: [number, number, number];
9
10
  };
@@ -1,4 +1,10 @@
1
- export { WormholeLayer } from './layer';
2
- export { WormholeSimulation } from './simulation';
3
- export type { WormholeSimulationConfig } from './simulation';
1
+ import { Wormhole } from './layer';
2
+ import type { WormholeConfig } from './layer';
3
+ import type { Effect } from '../effect';
4
+
5
+ export function createWormhole(config?: WormholeConfig): Effect<WormholeConfig> {
6
+ return new Wormhole(config);
7
+ }
8
+
9
+ export type { WormholeConfig };
4
10
  export type { WormholeDirection, WormholeParticle } from './types';
@@ -1,21 +1,28 @@
1
1
  import { hexToRGB } from '@basmilius/utils';
2
- import { SimulationLayer } from '../layer';
2
+ import { Effect } from '../effect';
3
3
  import { MULBERRY } from './consts';
4
- import type { WormholeSimulationConfig } from './simulation';
5
4
  import type { WormholeDirection, WormholeParticle } from './types';
6
5
 
7
- export class WormholeLayer extends SimulationLayer {
8
- readonly #speed: number;
6
+ export interface WormholeConfig {
7
+ readonly count?: number;
8
+ readonly speed?: number;
9
+ readonly color?: string;
10
+ readonly direction?: WormholeDirection;
11
+ readonly scale?: number;
12
+ }
13
+
14
+ export class Wormhole extends Effect<WormholeConfig> {
15
+ #speed: number;
9
16
  readonly #colorRGB: [number, number, number];
10
17
  readonly #direction: WormholeDirection;
11
- readonly #scale: number;
18
+ #scale: number;
12
19
  #count: number;
13
20
  #particles: WormholeParticle[] = [];
14
21
  #width: number = 960;
15
22
  #height: number = 540;
16
23
  #initialized: boolean = false;
17
24
 
18
- constructor(config: WormholeSimulationConfig = {}) {
25
+ constructor(config: WormholeConfig = {}) {
19
26
  super();
20
27
 
21
28
  let count = config.count ?? 200;
@@ -46,6 +53,15 @@ export class WormholeLayer extends SimulationLayer {
46
53
  }
47
54
  }
48
55
 
56
+ configure(config: Partial<WormholeConfig>): void {
57
+ if (config.speed !== undefined) {
58
+ this.#speed = config.speed;
59
+ }
60
+ if (config.scale !== undefined) {
61
+ this.#scale = config.scale;
62
+ }
63
+ }
64
+
49
65
  tick(dt: number, width: number, height: number): void {
50
66
  this.#width = width;
51
67
  this.#height = height;
@@ -1,19 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { AuroraLayer } from './layer';
3
-
4
- export interface AuroraSimulationConfig {
5
- readonly bands?: number;
6
- readonly colors?: string[];
7
- readonly speed?: number;
8
- readonly intensity?: number;
9
- readonly waveAmplitude?: number;
10
- readonly verticalPosition?: number;
11
- readonly scale?: number;
12
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
13
- }
14
-
15
- export class AuroraSimulation extends SimulationCanvas {
16
- constructor(canvas: HTMLCanvasElement, config: AuroraSimulationConfig = {}) {
17
- super(canvas, new AuroraLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
18
- }
19
- }
@@ -1,19 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { BalloonLayer } from './layer';
3
-
4
- export interface BalloonSimulationConfig {
5
- readonly count?: number;
6
- readonly colors?: string[];
7
- readonly sizeRange?: [number, number];
8
- readonly speed?: number;
9
- readonly driftAmount?: number;
10
- readonly stringLength?: number;
11
- readonly scale?: number;
12
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
13
- }
14
-
15
- export class BalloonSimulation extends SimulationCanvas {
16
- constructor(canvas: HTMLCanvasElement, config: BalloonSimulationConfig = {}) {
17
- super(canvas, new BalloonLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
18
- }
19
- }
@@ -1,20 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { BubbleLayer } from './layer';
3
-
4
- export interface BubbleSimulationConfig {
5
- readonly count?: number;
6
- readonly sizeRange?: [number, number];
7
- readonly speed?: number;
8
- readonly popOnClick?: boolean;
9
- readonly popRadius?: number;
10
- readonly colors?: string[];
11
- readonly wobbleAmount?: number;
12
- readonly scale?: number;
13
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
14
- }
15
-
16
- export class BubbleSimulation extends SimulationCanvas {
17
- constructor(canvas: HTMLCanvasElement, config: BubbleSimulationConfig = {}) {
18
- super(canvas, new BubbleLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
19
- }
20
- }
@@ -1,27 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { ConfettiLayer } from './layer';
3
- import type { Config } from './types';
4
-
5
- export interface ConfettiSimulationConfig {
6
- readonly scale?: number;
7
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
8
- }
9
-
10
- export class ConfettiSimulation extends SimulationCanvas {
11
- readonly #layer: ConfettiLayer;
12
-
13
- constructor(canvas: HTMLCanvasElement, config: ConfettiSimulationConfig = {}) {
14
- const layer = new ConfettiLayer(config);
15
- super(canvas, layer, 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
16
- this.#layer = layer;
17
- }
18
-
19
- fire(config: Partial<Config>): void {
20
- this.onResize();
21
- this.#layer.fire(config);
22
-
23
- if (!this.isTicking) {
24
- this.start();
25
- }
26
- }
27
- }
@@ -1,25 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { DonutLayer } from './layer';
3
-
4
- export interface DonutSimulationConfig {
5
- readonly background?: string;
6
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
7
- readonly collisionPadding?: number;
8
- readonly colors?: string[];
9
- readonly count?: number;
10
- readonly mouseAvoidance?: boolean;
11
- readonly mouseAvoidanceRadius?: number;
12
- readonly mouseAvoidanceStrength?: number;
13
- readonly radiusRange?: [number, number];
14
- readonly repulsionStrength?: number;
15
- readonly rotationSpeedRange?: [number, number];
16
- readonly scale?: number;
17
- readonly speedRange?: [number, number];
18
- readonly thickness?: number;
19
- }
20
-
21
- export class DonutSimulation extends SimulationCanvas {
22
- constructor(canvas: HTMLCanvasElement, config: DonutSimulationConfig = {}) {
23
- super(canvas, new DonutLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
24
- }
25
- }
@@ -1,18 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { FireflyLayer } from './layer';
3
-
4
- export interface FireflySimulationConfig {
5
- readonly count?: number;
6
- readonly color?: string;
7
- readonly size?: number;
8
- readonly speed?: number;
9
- readonly glowSpeed?: number;
10
- readonly scale?: number;
11
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
12
- }
13
-
14
- export class FireflySimulation extends SimulationCanvas {
15
- constructor(canvas: HTMLCanvasElement, config: FireflySimulationConfig = {}) {
16
- super(canvas, new FireflyLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
17
- }
18
- }
@@ -1,17 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { FirepitLayer } from './layer';
3
-
4
- export interface FirepitSimulationConfig {
5
- readonly embers?: number;
6
- readonly flameWidth?: number;
7
- readonly flameHeight?: number;
8
- readonly intensity?: number;
9
- readonly scale?: number;
10
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
11
- }
12
-
13
- export class FirepitSimulation extends SimulationCanvas {
14
- constructor(canvas: HTMLCanvasElement, config: FirepitSimulationConfig = {}) {
15
- super(canvas, new FirepitLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
16
- }
17
- }
@@ -1,18 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { FireworkLayer } from './layer';
3
- import type { Point } from '../point';
4
- import type { FireworkSimulationConfig, FireworkVariant } from './types';
5
-
6
- export class FireworkSimulation extends SimulationCanvas {
7
- readonly #layer: FireworkLayer;
8
-
9
- constructor(canvas: HTMLCanvasElement, config: FireworkSimulationConfig = {}) {
10
- const layer = new FireworkLayer(config);
11
- super(canvas, layer, 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
12
- this.#layer = layer;
13
- }
14
-
15
- fireExplosion(variant: FireworkVariant, position?: Point): void {
16
- this.#layer.fireExplosion(variant, position);
17
- }
18
- }
@@ -1,19 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { GlitterLayer } from './layer';
3
-
4
- export interface GlitterSimulationConfig {
5
- readonly count?: number;
6
- readonly colors?: string[];
7
- readonly size?: number;
8
- readonly speed?: number;
9
- readonly groundLevel?: number;
10
- readonly maxSettled?: number;
11
- readonly scale?: number;
12
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
13
- }
14
-
15
- export class GlitterSimulation extends SimulationCanvas {
16
- constructor(canvas: HTMLCanvasElement, config: GlitterSimulationConfig = {}) {
17
- super(canvas, new GlitterLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
18
- }
19
- }
@@ -1,17 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { LanternLayer } from './layer';
3
-
4
- export interface LanternSimulationConfig {
5
- readonly count?: number;
6
- readonly colors?: string[];
7
- readonly size?: number;
8
- readonly speed?: number;
9
- readonly scale?: number;
10
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
11
- }
12
-
13
- export class LanternSimulation extends SimulationCanvas {
14
- constructor(canvas: HTMLCanvasElement, config: LanternSimulationConfig = {}) {
15
- super(canvas, new LanternLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
16
- }
17
- }
package/src/layered.ts DELETED
@@ -1,185 +0,0 @@
1
- import { LimitedFrameRateCanvas } from './canvas';
2
- import type { EdgeFade, EdgeFadeSide, SimulationLayer } from './layer';
3
-
4
- function parseSide(side: EdgeFadeSide): [number, number] {
5
- return typeof side === 'number' ? [0, side] : side;
6
- }
7
-
8
-
9
- function applyEdgeFade(ctx: CanvasRenderingContext2D, width: number, height: number, fade: EdgeFade): void {
10
- ctx.globalCompositeOperation = 'destination-out';
11
-
12
- if (fade.top !== undefined) {
13
- const [near, far] = parseSide(fade.top);
14
- const nearPx = near * height;
15
- const farPx = far * height;
16
-
17
- if (nearPx > 0) {
18
- ctx.fillStyle = 'rgba(0,0,0,1)';
19
- ctx.fillRect(0, 0, width, nearPx);
20
- }
21
-
22
- if (farPx > nearPx) {
23
- const gradient = ctx.createLinearGradient(0, nearPx, 0, farPx);
24
- gradient.addColorStop(0, 'rgba(0,0,0,1)');
25
- gradient.addColorStop(1, 'rgba(0,0,0,0)');
26
- ctx.fillStyle = gradient;
27
- ctx.fillRect(0, nearPx, width, farPx - nearPx);
28
- }
29
- }
30
-
31
- if (fade.bottom !== undefined) {
32
- const [near, far] = parseSide(fade.bottom);
33
- const nearPx = near * height;
34
- const farPx = far * height;
35
-
36
- if (nearPx > 0) {
37
- ctx.fillStyle = 'rgba(0,0,0,1)';
38
- ctx.fillRect(0, height - nearPx, width, nearPx);
39
- }
40
-
41
- if (farPx > nearPx) {
42
- const gradient = ctx.createLinearGradient(0, height - farPx, 0, height - nearPx);
43
- gradient.addColorStop(0, 'rgba(0,0,0,0)');
44
- gradient.addColorStop(1, 'rgba(0,0,0,1)');
45
- ctx.fillStyle = gradient;
46
- ctx.fillRect(0, height - farPx, width, farPx - nearPx);
47
- }
48
- }
49
-
50
- if (fade.left !== undefined) {
51
- const [near, far] = parseSide(fade.left);
52
- const nearPx = near * width;
53
- const farPx = far * width;
54
-
55
- if (nearPx > 0) {
56
- ctx.fillStyle = 'rgba(0,0,0,1)';
57
- ctx.fillRect(0, 0, nearPx, height);
58
- }
59
-
60
- if (farPx > nearPx) {
61
- const gradient = ctx.createLinearGradient(nearPx, 0, farPx, 0);
62
- gradient.addColorStop(0, 'rgba(0,0,0,1)');
63
- gradient.addColorStop(1, 'rgba(0,0,0,0)');
64
- ctx.fillStyle = gradient;
65
- ctx.fillRect(nearPx, 0, farPx - nearPx, height);
66
- }
67
- }
68
-
69
- if (fade.right !== undefined) {
70
- const [near, far] = parseSide(fade.right);
71
- const nearPx = near * width;
72
- const farPx = far * width;
73
-
74
- if (nearPx > 0) {
75
- ctx.fillStyle = 'rgba(0,0,0,1)';
76
- ctx.fillRect(width - nearPx, 0, nearPx, height);
77
- }
78
-
79
- if (farPx > nearPx) {
80
- const gradient = ctx.createLinearGradient(width - farPx, 0, width - nearPx, 0);
81
- gradient.addColorStop(0, 'rgba(0,0,0,0)');
82
- gradient.addColorStop(1, 'rgba(0,0,0,1)');
83
- ctx.fillStyle = gradient;
84
- ctx.fillRect(width - farPx, 0, farPx - nearPx, height);
85
- }
86
- }
87
-
88
- ctx.globalCompositeOperation = 'source-over';
89
- }
90
-
91
- export class LayeredSimulation extends LimitedFrameRateCanvas {
92
- readonly #layers: SimulationLayer[] = [];
93
- readonly #contextOptions: CanvasRenderingContext2DSettings;
94
- #offscreen: HTMLCanvasElement | null = null;
95
- #offscreenCtx: CanvasRenderingContext2D | null = null;
96
-
97
- constructor(canvas: HTMLCanvasElement, frameRate: number = 60, options: CanvasRenderingContext2DSettings = {colorSpace: 'display-p3'}) {
98
- super(canvas, frameRate, options);
99
- this.#contextOptions = options;
100
-
101
- canvas.style.position = 'absolute';
102
- canvas.style.top = '0';
103
- canvas.style.left = '0';
104
- canvas.style.height = '100%';
105
- canvas.style.width = '100%';
106
- }
107
-
108
- add(layer: SimulationLayer): this {
109
- this.#layers.push(layer);
110
-
111
- if (this.isTicking) {
112
- layer.onMount(this.canvas);
113
- }
114
-
115
- return this;
116
- }
117
-
118
- start(): void {
119
- for (const layer of this.#layers) {
120
- layer.onMount(this.canvas);
121
- }
122
- super.start();
123
- }
124
-
125
- destroy(): void {
126
- for (const layer of this.#layers) {
127
- layer.onUnmount(this.canvas);
128
- }
129
- super.destroy();
130
- }
131
-
132
- draw(): void {
133
- this.canvas.height = this.height;
134
- this.canvas.width = this.width;
135
-
136
- const ctx = this.context;
137
- ctx.clearRect(0, 0, this.width, this.height);
138
-
139
- for (const layer of this.#layers) {
140
- if (layer.fade) {
141
- const offCtx = this.#getOffscreenCtx(this.width, this.height);
142
- offCtx.clearRect(0, 0, this.width, this.height);
143
- layer.draw(offCtx, this.width, this.height);
144
- applyEdgeFade(offCtx, this.width, this.height, layer.fade);
145
- ctx.drawImage(this.#offscreen!, 0, 0);
146
- } else {
147
- ctx.save();
148
- layer.draw(ctx, this.width, this.height);
149
- ctx.restore();
150
- }
151
- }
152
- }
153
-
154
- tick(): void {
155
- const dt = (this.delta > 0 && this.delta < 200 ? this.delta / (1000 / 60) : 1) * this.speed * LimitedFrameRateCanvas.globalSpeed;
156
-
157
- for (const layer of this.#layers) {
158
- layer.tick(dt, this.width, this.height);
159
- }
160
- }
161
-
162
- onResize(): void {
163
- super.onResize();
164
-
165
- if (this.#offscreen) {
166
- this.#offscreen.width = this.width;
167
- this.#offscreen.height = this.height;
168
- }
169
-
170
- for (const layer of this.#layers) {
171
- layer.onResize(this.width, this.height);
172
- }
173
- }
174
-
175
- #getOffscreenCtx(width: number, height: number): CanvasRenderingContext2D {
176
- if (!this.#offscreen) {
177
- this.#offscreen = document.createElement('canvas');
178
- this.#offscreen.width = width;
179
- this.#offscreen.height = height;
180
- this.#offscreenCtx = this.#offscreen.getContext('2d', this.#contextOptions)!;
181
- }
182
-
183
- return this.#offscreenCtx!;
184
- }
185
- }
@@ -1,18 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { LeafLayer } from './layer';
3
-
4
- export interface LeafSimulationConfig {
5
- readonly count?: number;
6
- readonly colors?: string[];
7
- readonly size?: number;
8
- readonly speed?: number;
9
- readonly wind?: number;
10
- readonly scale?: number;
11
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
12
- }
13
-
14
- export class LeafSimulation extends SimulationCanvas {
15
- constructor(canvas: HTMLCanvasElement, config: LeafSimulationConfig = {}) {
16
- super(canvas, new LeafLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
17
- }
18
- }
@@ -1,17 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { LightningLayer } from './layer';
3
-
4
- export interface LightningSimulationConfig {
5
- readonly frequency?: number;
6
- readonly color?: string;
7
- readonly branches?: boolean;
8
- readonly flash?: boolean;
9
- readonly scale?: number;
10
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
11
- }
12
-
13
- export class LightningSimulation extends SimulationCanvas {
14
- constructor(canvas: HTMLCanvasElement, config: LightningSimulationConfig = {}) {
15
- super(canvas, new LightningLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
16
- }
17
- }
@@ -1,18 +0,0 @@
1
- import { SimulationCanvas } from '../simulation-canvas';
2
- import { MatrixLayer } from './layer';
3
-
4
- export interface MatrixSimulationConfig {
5
- readonly columns?: number;
6
- readonly speed?: number;
7
- readonly color?: string;
8
- readonly fontSize?: number;
9
- readonly trailLength?: number;
10
- readonly scale?: number;
11
- readonly canvasOptions?: CanvasRenderingContext2DSettings;
12
- }
13
-
14
- export class MatrixSimulation extends SimulationCanvas {
15
- constructor(canvas: HTMLCanvasElement, config: MatrixSimulationConfig = {}) {
16
- super(canvas, new MatrixLayer(config), 60, config.canvasOptions ?? {colorSpace: 'display-p3'});
17
- }
18
- }