3d-spinner 0.9.0 → 0.9.2

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 (29) hide show
  1. package/README.md +49 -8
  2. package/dist/animations/object-motion.d.ts +4 -1
  3. package/dist/animations/object-motion.js +2 -1
  4. package/dist/animations/spin.d.ts +4 -1
  5. package/dist/animations/spin.js +2 -1
  6. package/dist/cjs/animations/object-motion.cjs +1368 -0
  7. package/dist/cjs/animations/spin.cjs +1299 -0
  8. package/dist/cjs/engines/little-3d-engine/little-3d-engine.cjs +1324 -0
  9. package/dist/cjs/engines/little-3d-engine/loaders/obj.cjs +58 -0
  10. package/dist/cjs/engines/little-tween-engine/little-tween-engine.cjs +279 -0
  11. package/dist/cjs/index.cjs +120 -0
  12. package/dist/cjs/motion/motion.cjs +140 -0
  13. package/dist/cjs/motion/transitions.cjs +80 -0
  14. package/dist/engines/little-3d-engine/core/mesh.d.ts +18 -0
  15. package/dist/engines/little-3d-engine/little-3d-engine.d.ts +10 -3
  16. package/dist/engines/little-3d-engine/little-3d-engine.js +12 -8
  17. package/dist/engines/little-3d-engine/loaders/obj.d.ts +2 -2
  18. package/dist/engines/little-3d-engine/loaders/obj.js +2 -2
  19. package/dist/engines/little-3d-engine/renderer.d.ts +15 -1
  20. package/dist/engines/little-3d-engine/renderer.js +36 -0
  21. package/dist/engines/little-3d-engine/renderers/canvas2d.d.ts +1 -1
  22. package/dist/engines/little-3d-engine/renderers/canvas2d.js +22 -2
  23. package/dist/engines/little-3d-engine/renderers/webgl.d.ts +1 -1
  24. package/dist/engines/little-3d-engine/renderers/webgl.js +38 -1
  25. package/dist/engines/little-3d-engine/renderers/webgpu.d.ts +3 -1
  26. package/dist/engines/little-3d-engine/renderers/webgpu.js +70 -17
  27. package/dist/umd/spinner.global.js +2408 -0
  28. package/dist/umd/spinner.global.min.js +58 -0
  29. package/package.json +26 -11
package/README.md CHANGED
@@ -1,12 +1,13 @@
1
- # 3d-spinner
1
+ # 3d-spinner and beyond
2
2
 
3
3
  [![tests](https://img.shields.io/github/actions/workflow/status/runelaang/3d-spinner/ci.yml?label=tests&logo=github)](https://github.com/runelaang/3d-spinner/actions/workflows/ci.yml)
4
4
  [![npm](https://img.shields.io/npm/v/3d-spinner?logo=npm)](https://www.npmjs.com/package/3d-spinner)
5
5
  [![license](https://img.shields.io/github/license/runelaang/3d-spinner)](LICENSE)
6
6
 
7
7
  A zero-dependency 3D spinner, loader, and progress indicator for the browser. It renders to a
8
- canvas and ships as ES modules split across separate import paths, so a consumer loads only the
9
- animation, motion path, and rendering backend they actually use - nothing else is pulled in.
8
+ canvas and ships primarily as ES modules split across separate import paths, so a consumer loads
9
+ only the animation, motion path, and rendering backend they actually use - nothing else is pulled
10
+ in. CommonJS and a browser-global build are also published; see [Module formats](#module-formats).
10
11
 
11
12
  ## Install
12
13
 
@@ -145,6 +146,24 @@ do not use is never fetched.
145
146
  new SpinAnimation({ backend: "webgl" }); // "canvas2d" (default), "webgl", or "webgpu"
146
147
  ```
147
148
 
149
+ Renderer-specific features can look different between Canvas 2D, WebGL, and WebGPU. In
150
+ particular, transparent shapes are an approximate visual effect rather than a pixel-identical
151
+ cross-renderer result.
152
+
153
+ Use `transparency.mode` to choose visible-front-face transparency or a two-pass transparent-solid
154
+ effect. Opacity defaults to `0.35` for one-sided rendering. Two-sided rendering defaults to
155
+ front `0.56` and back `0.84`.
156
+
157
+ ```js
158
+ new SpinAnimation({
159
+ backend: "webgl",
160
+ transparency: { mode: "two-sided", opacity: 0.6 }, // front 0.6, back 0.4
161
+ });
162
+ ```
163
+
164
+ For two-sided rendering, explicit `frontOpacity` and `backOpacity` values override the shorthand
165
+ for their respective sides.
166
+
148
167
  ## The engine
149
168
 
150
169
  The renderer is a small, self-contained 3D engine, exported on its own in case you want it
@@ -157,17 +176,39 @@ directly:
157
176
 
158
177
  Each has no dependencies of its own.
159
178
 
160
- ## Module format
179
+ ## Module formats
161
180
 
162
- ES modules only, for the browser. Use a bundler or native `<script type="module">`; the engine
163
- draws to a canvas, so there is no server-side rendering. ES modules do not load over `file://`,
164
- so serve the page over HTTP rather than opening the file directly.
181
+ Every example above is **ES modules** - the primary, tree-shakeable format. Use a bundler or native `<script type="module">`; the engine draws to a canvas, so
182
+ there is no server-side rendering. ES modules do not load over `file://`, so serve the page over
183
+ HTTP rather than opening the file directly.
184
+
185
+ Two other formats are published for cases where ESM isn't an option:
186
+
187
+ **CommonJS** (`require`), for older Node tooling:
188
+
189
+ ```js
190
+ const { createSpinner } = require("3d-spinner");
191
+ const { SpinAnimation } = require("3d-spinner/animations/spin");
192
+ ```
193
+
194
+ **Browser global** (IIFE), for a plain `<script>` tag with no bundler or module loader. This build
195
+ bundles the whole public API onto one `window.Spinner3D` object:
196
+
197
+ ```html
198
+ <script src="https://unpkg.com/3d-spinner"></script>
199
+ <script>
200
+ const spinner = Spinner3D.createSpinner(document.getElementById("app"), {
201
+ type: "indeterminate",
202
+ animation: new Spinner3D.SpinAnimation(),
203
+ });
204
+ </script>
205
+ ```
165
206
 
166
207
  ## Development
167
208
 
168
209
  ```sh
169
210
  npm install
170
- npm run build # compile src/ to dist/ (ESM + type declarations)
211
+ npm run build # compile src/ to dist/ (ESM + type declarations, CJS, and a browser-global build)
171
212
  npm test # build, then run the unit tests
172
213
  npm run dev # serve this folder; open /examples/index.html
173
214
  ```
@@ -1,5 +1,5 @@
1
1
  import type { AnimationFrame, SpinnerAnimation } from "../animation.js";
2
- import { type Backend, type Mesh } from "../engines/little-3d-engine/little-3d-engine.js";
2
+ import { type Backend, type Mesh, type Transparency } from "../engines/little-3d-engine/little-3d-engine.js";
3
3
  import type { MotionController } from "../motion/controller.js";
4
4
  import { type ObjectMotionTransitionConfig } from "../motion/transitions.js";
5
5
  /** Which local axis the object's nose points down, used to correct a model that moves backwards or sideways. */
@@ -31,6 +31,8 @@ export interface ObjectMotionOptions {
31
31
  color?: string;
32
32
  /** Rendering backend. Default `"canvas2d"`. */
33
33
  backend?: Backend;
34
+ /** Optional one-sided or two-sided mesh transparency. */
35
+ transparency?: Transparency;
34
36
  /** Uniform object size after centering. Default `1`. */
35
37
  size?: number;
36
38
  /** The object's nose axis. Set this to correct a model that moves backwards or sideways. Default `"+x"`. */
@@ -65,6 +67,7 @@ export declare class ObjectMotionAnimation implements SpinnerAnimation {
65
67
  private readonly mesh;
66
68
  private readonly motion;
67
69
  private readonly backend?;
70
+ private readonly transparency?;
68
71
  private readonly labelText?;
69
72
  private readonly tailCount;
70
73
  private readonly tailGap;
@@ -159,6 +159,7 @@ export class ObjectMotionAnimation {
159
159
  this.mesh = applyColor(facing, options.color ?? "#cbd5e1");
160
160
  this.motion = options.motion;
161
161
  this.backend = options.backend;
162
+ this.transparency = options.transparency;
162
163
  this.labelText = options.label;
163
164
  this.tailCount = Math.max(0, Math.floor(options.tail?.count ?? 0));
164
165
  this.tailGap = Math.max(0, options.tail?.gapMs ?? 0);
@@ -186,7 +187,7 @@ export class ObjectMotionAnimation {
186
187
  camera: { position: { x: 0, y: 0, z: 3 } },
187
188
  });
188
189
  for (let i = 0; i <= this.tailCount; i++) {
189
- this.handles.push(engine.add(this.mesh));
190
+ this.handles.push(engine.add(this.mesh, { transparency: this.transparency }));
190
191
  this.banks.push(0);
191
192
  this.headings.push({ x: 1, y: 0, z: 0 });
192
193
  }
@@ -1,5 +1,5 @@
1
1
  import type { AnimationFrame, SpinnerAnimation } from "../animation.js";
2
- import { type Backend, type Mesh } from "../engines/little-3d-engine/little-3d-engine.js";
2
+ import { type Backend, type Mesh, type Transparency } from "../engines/little-3d-engine/little-3d-engine.js";
3
3
  import { type ProgressAnimationOptions } from "../progress-animation.js";
4
4
  export interface SpinAnimationOptions {
5
5
  /** Shape to spin: a mesh, or a factory that returns one. Default: a cube. */
@@ -12,6 +12,8 @@ export interface SpinAnimationOptions {
12
12
  spinY?: number;
13
13
  /** Rendering backend. Default `"canvas2d"`. */
14
14
  backend?: Backend;
15
+ /** Optional one-sided or two-sided mesh transparency. */
16
+ transparency?: Transparency;
15
17
  /**
16
18
  * Enable the start/end pop and progress-driven scale, with an optional overlay
17
19
  * label. Omit to spin at constant size with no progress reaction.
@@ -31,6 +33,7 @@ export declare class SpinAnimation implements SpinnerAnimation {
31
33
  private readonly spinX;
32
34
  private readonly spinY;
33
35
  private readonly backend?;
36
+ private readonly transparency?;
34
37
  private readonly progress?;
35
38
  private exited;
36
39
  constructor(options?: SpinAnimationOptions);
@@ -36,6 +36,7 @@ export class SpinAnimation {
36
36
  this.spinX = options.spinX ?? 0.0007;
37
37
  this.spinY = options.spinY ?? 0.0011;
38
38
  this.backend = options.backend;
39
+ this.transparency = options.transparency;
39
40
  this.progress = options.progressAnimation
40
41
  ? new ProgressAnimation(options.progressAnimation)
41
42
  : undefined;
@@ -46,7 +47,7 @@ export class SpinAnimation {
46
47
  backend: this.backend,
47
48
  camera: { position: { x: 0, y: 0, z: 2.8 } },
48
49
  });
49
- this.handle = engine.add(this.mesh);
50
+ this.handle = engine.add(this.mesh, { transparency: this.transparency });
50
51
  this.engine = engine;
51
52
  engine.mount(target).catch((error) => {
52
53
  target.textContent = error instanceof Error ? error.message : String(error);