3d-spinner 0.9.3 → 0.9.4

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.
@@ -1,2 +1,14 @@
1
- /** A white five-point star on a transparent square canvas. */
2
- export declare function starTexture(): HTMLCanvasElement;
1
+ /** Options for {@link starTexture}. */
2
+ export interface StarTextureOptions {
3
+ /**
4
+ * Radius of a soft glow drawn around the star, in canvas pixels. A blurred
5
+ * copy of the star is composited underneath the crisp one, so the glow takes
6
+ * the particle's tint. Default `0` (no glow).
7
+ */
8
+ glow?: number;
9
+ }
10
+ /**
11
+ * A white five-point star on a transparent square canvas. With `glow`, a
12
+ * blurred copy is composited beneath the crisp star for a soft halo.
13
+ */
14
+ export declare function starTexture(options?: StarTextureOptions): HTMLCanvasElement;
@@ -1,16 +1,31 @@
1
1
  import { canvasTexture } from "./canvas-texture.js";
2
- /** A white five-point star on a transparent square canvas. */
3
- export function starTexture() {
2
+ function drawStar(ctx) {
3
+ ctx.save();
4
+ ctx.translate(48, 48);
5
+ ctx.fillStyle = "#fff";
6
+ ctx.beginPath();
7
+ for (let index = 0; index < 10; index++) {
8
+ const radius = index % 2 === 0 ? 43 : 16;
9
+ const angle = (index * Math.PI) / 5 - Math.PI / 2;
10
+ ctx.lineTo(radius * Math.cos(angle), radius * Math.sin(angle));
11
+ }
12
+ ctx.closePath();
13
+ ctx.fill();
14
+ ctx.restore();
15
+ }
16
+ /**
17
+ * A white five-point star on a transparent square canvas. With `glow`, a
18
+ * blurred copy is composited beneath the crisp star for a soft halo.
19
+ */
20
+ export function starTexture(options = {}) {
21
+ const glow = Math.max(0, options.glow ?? 0);
4
22
  return canvasTexture((ctx) => {
5
- ctx.translate(48, 48);
6
- ctx.fillStyle = "#fff";
7
- ctx.beginPath();
8
- for (let index = 0; index < 10; index++) {
9
- const radius = index % 2 === 0 ? 43 : 16;
10
- const angle = (index * Math.PI) / 5 - Math.PI / 2;
11
- ctx.lineTo(radius * Math.cos(angle), radius * Math.sin(angle));
23
+ if (glow > 0) {
24
+ ctx.save();
25
+ ctx.filter = `blur(${glow}px)`;
26
+ drawStar(ctx);
27
+ ctx.restore();
12
28
  }
13
- ctx.closePath();
14
- ctx.fill();
29
+ drawStar(ctx);
15
30
  });
16
31
  }
@@ -1,9 +1,10 @@
1
1
  import type { ProgressSpinnerOptions } from "../index.js";
2
2
  import type { MotionProgressPrefabOptions } from "./types.js";
3
3
  /**
4
- * A progress story: a translucent train of ice cubes pulls in and runs laps
5
- * around a tilted square track, shedding a trail of pale stars while progress
6
- * climbs; at 100% the whole convoy flies off along the track, cars following
7
- * the lead one by one, and the star trail drains behind them.
4
+ * A progress story: a translucent train of ice cubes runs laps around a tilted
5
+ * square track, shedding a trail of pale stars. Every 2% of progress attaches
6
+ * one more car, popping it into existence at the tail; at 100% the whole convoy
7
+ * peels off the track one after another and accelerates away, clearing the view
8
+ * within four seconds as the star trail drains behind it.
8
9
  */
9
10
  export declare function ghostTrain(options?: MotionProgressPrefabOptions): ProgressSpinnerOptions;
@@ -1,44 +1,37 @@
1
1
  import { CompositeAnimation } from "../composite-animation.js";
2
- import { ObjectMotionAnimation } from "../animations/object-motion.js";
2
+ import { GhostTrainAnimation } from "../animations/ghost-train.js";
3
3
  import { ParticlesAnimation } from "../animations/particles.js";
4
- import { cube, starTexture } from "../engines/little-3d-engine/little-3d-engine.js";
5
- import { squareMotion } from "../motion/square.js";
4
+ import { starTexture } from "../engines/little-3d-engine/little-3d-engine.js";
6
5
  import { progressSpinner } from "./spinner.js";
7
6
  /**
8
- * A progress story: a translucent train of ice cubes pulls in and runs laps
9
- * around a tilted square track, shedding a trail of pale stars while progress
10
- * climbs; at 100% the whole convoy flies off along the track, cars following
11
- * the lead one by one, and the star trail drains behind them.
7
+ * A progress story: a translucent train of ice cubes runs laps around a tilted
8
+ * square track, shedding a trail of pale stars. Every 2% of progress attaches
9
+ * one more car, popping it into existence at the tail; at 100% the whole convoy
10
+ * peels off the track one after another and accelerates away, clearing the view
11
+ * within four seconds as the star trail drains behind it.
12
12
  */
13
13
  export function ghostTrain(options = {}) {
14
- const motion = options.object?.motion ?? squareMotion({ size: 1.7, periodMs: 6800, tilt: 0.5 });
15
14
  const particles = options.particles ?? {};
16
- // The object defines the primary direction; the particles trail its actual position through
17
- // the intro/outro fly transitions (not the bare path), so the two layers stay in sync.
18
- const object = new ObjectMotionAnimation({
19
- mesh: () => cube(1, ["#bae6fd", "#7dd3fc", "#38bdf8", "#0ea5e9", "#a5f3fc", "#e0f2fe"]),
20
- motion,
21
- size: 0.3,
22
- transparency: { mode: "two-sided", opacity: 0.55 },
23
- tail: { count: 4, gapMs: 240 },
15
+ const train = new GhostTrainAnimation({
16
+ motion: options.object?.motion,
24
17
  backend: options.backend,
25
- ...options.object,
26
- label: options.object?.label,
27
18
  });
19
+ // The lead car defines the primary direction; the stars trail its actual position
20
+ // through the laps and the accelerating blast-off, so the two layers stay in sync.
28
21
  const trail = new ParticlesAnimation({
29
22
  rate: 30,
30
23
  lifeMs: 1700,
31
- size: 0.13,
32
- speed: 0.07,
24
+ size: 0.15,
25
+ speed: 0.11,
33
26
  colors: ["#e0f2fe", "#a5f3fc", "#c4b5fd"],
34
- texture: particles.texture ?? starTexture(),
35
- emitter: object.trailEmitter(),
36
- outroMs: object.outroDurationMs,
27
+ texture: particles.texture ?? starTexture({ glow: 5 }),
28
+ emitter: train.trailEmitter(),
29
+ outroMs: train.outroDurationMs,
37
30
  seed: 17,
38
31
  backend: options.backend,
39
32
  ...particles,
40
33
  label: options.label ?? particles.label,
41
34
  fadeLabel: options.fadeLabel ?? particles.fadeLabel,
42
35
  });
43
- return progressSpinner(new CompositeAnimation([trail, object]), options);
36
+ return progressSpinner(new CompositeAnimation([trail, train]), options);
44
37
  }
@@ -1,8 +1,10 @@
1
1
  import type { ProgressSpinnerOptions } from "../index.js";
2
- import type { MotionProgressPrefabOptions } from "./types.js";
2
+ import type { ProgressPrefabOptions } from "./types.js";
3
3
  /**
4
- * A progress story: a silver rocket glides in and patrols a slow loop on a
5
- * column of embers while progress climbs; at 100% it pitches up and blasts off
6
- * the top of the view, exhaust trailing behind it.
4
+ * A progress story on a launch pad: every 5% of progress a small rocket slides
5
+ * in cartoon-style from the right and lines up under the progress text, idling
6
+ * on a thin wisp of smoke. At 100% the whole row blasts off in a loose stagger
7
+ * on columns of fire; partway up, three of them suddenly veer 30-50 degrees and
8
+ * streak away.
7
9
  */
8
- export declare function rocketLaunch(options?: MotionProgressPrefabOptions): ProgressSpinnerOptions;
10
+ export declare function rocketLaunch(options?: ProgressPrefabOptions): ProgressSpinnerOptions;
@@ -1,59 +1,16 @@
1
- import { CompositeAnimation } from "../composite-animation.js";
2
- import { ObjectMotionAnimation } from "../animations/object-motion.js";
3
- import { ParticlesAnimation } from "../animations/particles.js";
4
- import { pyramid, shineTexture } from "../engines/little-3d-engine/little-3d-engine.js";
5
- import { easeInCubic } from "../engines/little-tween-engine/core/tweens.js";
6
- import { circleMotion } from "../motion/circle.js";
1
+ import { RocketLaunchAnimation } from "../animations/rocket-launch.js";
7
2
  import { progressSpinner } from "./spinner.js";
8
- // C1 launch: the handoff velocity coasts to a stop while the vertical climb
9
- // accelerates, so the nose rotates smoothly from the patrol tangent to straight up.
10
- const launchUp = ({ delta, position, velocity, durationMs }) => {
11
- const coast = durationMs * delta * (1 - 0.5 * delta);
12
- const climb = 5.5 * easeInCubic(delta);
13
- return {
14
- position: {
15
- x: position.x + (velocity?.x ?? 0) * coast,
16
- y: position.y + (velocity?.y ?? 0) * coast + climb,
17
- z: position.z + (velocity?.z ?? 0) * coast,
18
- },
19
- };
20
- };
21
3
  /**
22
- * A progress story: a silver rocket glides in and patrols a slow loop on a
23
- * column of embers while progress climbs; at 100% it pitches up and blasts off
24
- * the top of the view, exhaust trailing behind it.
4
+ * A progress story on a launch pad: every 5% of progress a small rocket slides
5
+ * in cartoon-style from the right and lines up under the progress text, idling
6
+ * on a thin wisp of smoke. At 100% the whole row blasts off in a loose stagger
7
+ * on columns of fire; partway up, three of them suddenly veer 30-50 degrees and
8
+ * streak away.
25
9
  */
26
10
  export function rocketLaunch(options = {}) {
27
- const motion = options.object?.motion
28
- ?? circleMotion({ radius: 0.55, periodMs: 7000, tilt: 0.15 });
29
- const particles = options.particles ?? {};
30
- const object = new ObjectMotionAnimation({
31
- mesh: () => pyramid(1, ["#e2e8f0", "#f8fafc", "#cbd5e1", "#94a3b8", "#e2e8f0"]),
32
- motion,
33
- size: 0.44,
34
- facing: "+y",
35
- outro: { transition: launchUp, durationMs: 1300 },
11
+ return progressSpinner(new RocketLaunchAnimation({
36
12
  backend: options.backend,
37
- ...options.object,
38
- label: options.object?.label,
39
- });
40
- const exhaust = new ParticlesAnimation({
41
- rate: 46,
42
- lifeMs: 1100,
43
- size: 0.18,
44
- speed: 0.5,
45
- direction: { x: 0, y: -1, z: 0 },
46
- spread: 0.3,
47
- gravity: { x: 0, y: -0.6, z: 0 },
48
- colors: ["#fde047", "#fb923c", "#ef4444", "#fef3c7"],
49
- texture: particles.texture ?? shineTexture(),
50
- emitter: object.trailEmitter(),
51
- outroMs: object.outroDurationMs,
52
- seed: 9,
53
- backend: options.backend,
54
- ...particles,
55
- label: options.label ?? particles.label,
56
- fadeLabel: options.fadeLabel ?? particles.fadeLabel,
57
- });
58
- return progressSpinner(new CompositeAnimation([exhaust, object]), options);
13
+ label: options.label,
14
+ fadeLabel: options.fadeLabel,
15
+ }), options);
59
16
  }