u-space 0.0.2 → 0.0.5

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.
@@ -3342,16 +3342,27 @@ function requireWhichTypedArray() {
3342
3342
  var O = r(E);
3343
3343
  S = p(O, Symbol.toStringTag);
3344
3344
  }
3345
- s["$" + m] = b(S.get);
3345
+ if (S && S.get) {
3346
+ var C = b(S.get);
3347
+ s[
3348
+ /** @type {`$${import('.').TypedArrayName}`} */
3349
+ "$" + m
3350
+ ] = C;
3351
+ }
3346
3352
  }
3347
3353
  }) : h(n, function(m) {
3348
3354
  var A = new t[m](), E = A.slice || A.set;
3349
- E && (s[
3350
- /** @type {`$${import('.').TypedArrayName}`} */
3351
- "$" + m
3352
- ] = /** @type {import('./types').BoundSlice | import('./types').BoundSet} */
3353
- // @ts-expect-error TODO FIXME
3354
- b(E));
3355
+ if (E) {
3356
+ var S = (
3357
+ /** @type {import('./types').BoundSlice | import('./types').BoundSet} */
3358
+ // @ts-expect-error TODO FIXME
3359
+ b(E)
3360
+ );
3361
+ s[
3362
+ /** @type {`$${import('.').TypedArrayName}`} */
3363
+ "$" + m
3364
+ ] = S;
3365
+ }
3355
3366
  });
3356
3367
  var l = function(A) {
3357
3368
  var E = !1;
@@ -4591,43 +4602,11 @@ function require_stream_duplex$1() {
4591
4602
  }
4592
4603
  }), _stream_duplex$1;
4593
4604
  }
4594
- var string_decoder = {}, safeBuffer = { exports: {} }, hasRequiredSafeBuffer;
4595
- function requireSafeBuffer() {
4596
- return hasRequiredSafeBuffer || (hasRequiredSafeBuffer = 1, (function(h, d) {
4597
- var b = requireDist(), u = b.Buffer;
4598
- function p(f, o) {
4599
- for (var t in f)
4600
- o[t] = f[t];
4601
- }
4602
- u.from && u.alloc && u.allocUnsafe && u.allocUnsafeSlow ? h.exports = b : (p(b, d), d.Buffer = r);
4603
- function r(f, o, t) {
4604
- return u(f, o, t);
4605
- }
4606
- p(u, r), r.from = function(f, o, t) {
4607
- if (typeof f == "number")
4608
- throw new TypeError("Argument must not be a number");
4609
- return u(f, o, t);
4610
- }, r.alloc = function(f, o, t) {
4611
- if (typeof f != "number")
4612
- throw new TypeError("Argument must be a number");
4613
- var n = u(f);
4614
- return o !== void 0 ? typeof t == "string" ? n.fill(o, t) : n.fill(o) : n.fill(0), n;
4615
- }, r.allocUnsafe = function(f) {
4616
- if (typeof f != "number")
4617
- throw new TypeError("Argument must be a number");
4618
- return u(f);
4619
- }, r.allocUnsafeSlow = function(f) {
4620
- if (typeof f != "number")
4621
- throw new TypeError("Argument must be a number");
4622
- return b.SlowBuffer(f);
4623
- };
4624
- })(safeBuffer, safeBuffer.exports)), safeBuffer.exports;
4625
- }
4626
- var hasRequiredString_decoder;
4605
+ var string_decoder = {}, hasRequiredString_decoder;
4627
4606
  function requireString_decoder() {
4628
4607
  if (hasRequiredString_decoder) return string_decoder;
4629
4608
  hasRequiredString_decoder = 1;
4630
- var h = requireSafeBuffer().Buffer, d = h.isEncoding || function(E) {
4609
+ var h = requireSafeBuffer$1().Buffer, d = h.isEncoding || function(E) {
4631
4610
  switch (E = "" + E, E && E.toLowerCase()) {
4632
4611
  case "hex":
4633
4612
  case "utf8":
@@ -5688,6 +5667,38 @@ var streamBrowser, hasRequiredStreamBrowser;
5688
5667
  function requireStreamBrowser() {
5689
5668
  return hasRequiredStreamBrowser || (hasRequiredStreamBrowser = 1, streamBrowser = requireEvents().EventEmitter), streamBrowser;
5690
5669
  }
5670
+ var safeBuffer = { exports: {} }, hasRequiredSafeBuffer;
5671
+ function requireSafeBuffer() {
5672
+ return hasRequiredSafeBuffer || (hasRequiredSafeBuffer = 1, (function(h, d) {
5673
+ var b = requireDist(), u = b.Buffer;
5674
+ function p(f, o) {
5675
+ for (var t in f)
5676
+ o[t] = f[t];
5677
+ }
5678
+ u.from && u.alloc && u.allocUnsafe && u.allocUnsafeSlow ? h.exports = b : (p(b, d), d.Buffer = r);
5679
+ function r(f, o, t) {
5680
+ return u(f, o, t);
5681
+ }
5682
+ p(u, r), r.from = function(f, o, t) {
5683
+ if (typeof f == "number")
5684
+ throw new TypeError("Argument must not be a number");
5685
+ return u(f, o, t);
5686
+ }, r.alloc = function(f, o, t) {
5687
+ if (typeof f != "number")
5688
+ throw new TypeError("Argument must be a number");
5689
+ var n = u(f);
5690
+ return o !== void 0 ? typeof t == "string" ? n.fill(o, t) : n.fill(o) : n.fill(0), n;
5691
+ }, r.allocUnsafe = function(f) {
5692
+ if (typeof f != "number")
5693
+ throw new TypeError("Argument must be a number");
5694
+ return u(f);
5695
+ }, r.allocUnsafeSlow = function(f) {
5696
+ if (typeof f != "number")
5697
+ throw new TypeError("Argument must be a number");
5698
+ return b.SlowBuffer(f);
5699
+ };
5700
+ })(safeBuffer, safeBuffer.exports)), safeBuffer.exports;
5701
+ }
5691
5702
  var util = {}, hasRequiredUtil;
5692
5703
  function requireUtil() {
5693
5704
  if (hasRequiredUtil) return util;
@@ -9898,7 +9909,7 @@ function requireBn$1() {
9898
9909
  var _ = 67108863 ^ 67108863 >>> g << g;
9899
9910
  this.words[this.length - 1] &= _;
9900
9911
  }
9901
- return this.strip();
9912
+ return this.length === 0 && (this.words[0] = 0, this.length = 1), this.strip();
9902
9913
  }, r.prototype.maskn = function(v) {
9903
9914
  return this.clone().imaskn(v);
9904
9915
  }, r.prototype.iaddn = function(v) {
@@ -11279,7 +11290,7 @@ function requireBn() {
11279
11290
  var q = 67108863 ^ 67108863 >>> _ << _;
11280
11291
  this.words[this.length - 1] &= q;
11281
11292
  }
11282
- return this._strip();
11293
+ return this.length === 0 && (this.words[0] = 0, this.length = 1), this._strip();
11283
11294
  }, r.prototype.maskn = function(c) {
11284
11295
  return this.clone().imaskn(c);
11285
11296
  }, r.prototype.iaddn = function(c) {
@@ -1,4 +1,4 @@
1
- import { type Object3D } from 'three/webgpu';
1
+ import { type Object3D, AnimationMixer, type AnimationAction, type AnimationClip } from 'three/webgpu';
2
2
  import { type InteractionEventMap } from '../interactions';
3
3
  import { BaseGroup } from './BaseGroup';
4
4
  export interface ModelParameters {
@@ -6,12 +6,25 @@ export interface ModelParameters {
6
6
  cache?: boolean;
7
7
  persistent?: boolean;
8
8
  }
9
+ export interface PlayAnimationOptions {
10
+ loop?: boolean;
11
+ repetitions?: number;
12
+ timeScale?: number;
13
+ clampWhenFinished?: boolean;
14
+ }
9
15
  export declare class Model extends BaseGroup<InteractionEventMap> {
10
16
  readonly isModel = true;
11
17
  type: string;
12
18
  private static memoryCache;
19
+ mixer: AnimationMixer | null;
20
+ animations: AnimationClip[];
21
+ private actions;
13
22
  constructor();
14
23
  loadAsync(parameters: ModelParameters): Promise<Object3D<import("three").Object3DEventMap> | null>;
24
+ playAnimation(nameOrIndex?: string | number, options?: PlayAnimationOptions): AnimationAction | null;
25
+ playAllAnimations(options?: PlayAnimationOptions): AnimationAction[];
26
+ stopAnimation(nameOrIndex?: string | number): void;
27
+ updateAnimation(delta: number): void;
15
28
  static clearMemoryCache(): void;
16
29
  static clearPersistentCache(): Promise<void>;
17
30
  }
@@ -21,11 +21,15 @@ export interface PoiParameters {
21
21
  borderRadius?: number;
22
22
  /** Text position relative to the icon */
23
23
  textPosition?: 'top' | 'bottom' | 'left' | 'right';
24
+ /** Scale factor for mapping canvas pixels to world units */
25
+ scaleFactor?: number;
24
26
  }
25
27
  export declare class Poi extends BaseSprite<InteractionEventMap> {
26
28
  readonly isPoi = true;
27
29
  type: string;
28
30
  parameters: Required<PoiParameters>;
31
+ private _canvas;
32
+ private _lastParametersJSON;
29
33
  constructor(parameters?: PoiParameters);
30
34
  /**
31
35
  * Update the POI with new parameters
@@ -14,15 +14,19 @@ export interface ViewerOptions {
14
14
  export interface ViewerEventMap {
15
15
  beforeControlsUpdate: {
16
16
  time: number;
17
+ delta: number;
17
18
  };
18
19
  afterControlsUpdate: {
19
20
  time: number;
21
+ delta: number;
20
22
  };
21
23
  beforeRender: {
22
24
  time: number;
25
+ delta: number;
23
26
  };
24
27
  afterRender: {
25
28
  time: number;
29
+ delta: number;
26
30
  };
27
31
  cameraChange: {
28
32
  camera: PerspectiveCamera | OrthographicCamera;
@@ -66,6 +66,64 @@ const model3 = new Model();
66
66
  model3.loadAsync({ url: 'model.glb', cache: true, persistent: true });
67
67
  ```
68
68
 
69
+ ### 动画
70
+
71
+ `Model` 在加载含内置动画的模型(如 glTF/FBX)后,会自动初始化 `AnimationMixer` 并收集 `AnimationClip`。
72
+
73
+ **属性:**
74
+
75
+ | 属性 | 类型 | 说明 |
76
+ | :----------- | :-------------------------- | :----------------------------------------- |
77
+ | `mixer` | `AnimationMixer \| null` | 动画混合器,加载含动画模型后自动创建。 |
78
+ | `animations` | `AnimationClip[]` | 模型内置的动画片段列表。 |
79
+
80
+ #### `playAnimation(nameOrIndex?, options?)`
81
+
82
+ 播放指定动画。不传参时播放第一个动画。
83
+
84
+ ```typescript
85
+ // 按名称播放
86
+ model.playAnimation('Walk');
87
+
88
+ // 按索引播放
89
+ model.playAnimation(0);
90
+
91
+ // 带选项
92
+ model.playAnimation('Run', {
93
+ loop: true, // 是否循环(默认 true)
94
+ repetitions: 3, // 循环次数(默认 Infinity)
95
+ timeScale: 1.5, // 播放速度(默认 1)
96
+ clampWhenFinished: true, // 播放结束后停留在最后一帧(默认 false)
97
+ });
98
+ ```
99
+
100
+ #### `playAllAnimations(options?)`
101
+
102
+ 播放模型所有内置动画。参数同 `playAnimation`。
103
+
104
+ ```typescript
105
+ model.playAllAnimations({ timeScale: 2 });
106
+ ```
107
+
108
+ #### `stopAnimation(nameOrIndex?)`
109
+
110
+ 停止指定动画。不传参时停止所有动画。
111
+
112
+ ```typescript
113
+ model.stopAnimation('Walk'); // 停止指定动画
114
+ model.stopAnimation(); // 停止所有动画
115
+ ```
116
+
117
+ #### `updateAnimation(delta)`
118
+
119
+ 推进动画时间,需在渲染循环中调用。`delta` 为帧间隔时间(秒),可从 Viewer 事件的 `delta` 属性获取。
120
+
121
+ ```typescript
122
+ viewer.addEventListener('beforeRender', (e) => {
123
+ model.updateAnimation(e.delta);
124
+ });
125
+ ```
126
+
69
127
  ### 清除缓存
70
128
 
71
129
  可通过 `Model` 类的静态方法手动清除内部缓存:
@@ -186,7 +244,9 @@ const poi = new Poi({
186
244
  backgroundColor: 'rgba(0,0,0,0.6)',
187
245
  textPosition: 'right',
188
246
  });
189
- await poi.updateAsync(); // 渲染 canvas 纹理
247
+ // 构造时会自动调用 updateAsync(),无需手动调用
248
+ // 如需更新参数,可再次调用:
249
+ // await poi.updateAsync({ text: '新文字' });
190
250
 
191
251
  poi.position.set(10, 5, 10);
192
252
  viewer.scene.add(poi);
@@ -203,15 +263,16 @@ viewer.scene.add(poi);
203
263
  | `color` | `string` | `'#ffffff'` | 文字颜色。 |
204
264
  | `iconSize` | `number` | `64` | 图标大小(像素)。 |
205
265
  | `padding` | `number` | `10` | 内容四周的内边距。 |
206
- | `backgroundColor` | `string` | `'rgba(0, 0, 0, 0.5)'` | 背景填充颜色。 |
266
+ | `backgroundColor` | `string` | `'rgba(0, 0, 0, 0)'` | 背景填充颜色。 |
207
267
  | `borderRadius` | `number` | `8` | 背景圆角半径。 |
208
268
  | `textPosition` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'right'` | 文字相对图标的位置。 |
269
+ | `scaleFactor` | `number` | `0.01` | canvas 像素到世界单位的缩放系数。 |
209
270
 
210
271
  ### 方法
211
272
 
212
273
  #### `updateAsync(parameters?)`
213
274
 
214
- 使用可选的参数覆盖重新渲染 canvas 纹理。
275
+ 使用可选的参数覆盖重新渲染 canvas 纹理。构造时会自动调用一次,后续参数未变化时会跳过重绘。
215
276
 
216
277
  ```typescript
217
278
  await poi.updateAsync({ text: '更新后的标签', color: '#ffff00' });
@@ -306,6 +367,25 @@ viewer.render();
306
367
 
307
368
  返回节点的邻接表(邻居 ID → 边权重)。
308
369
 
370
+ #### `exportData(): TopologyData`
371
+
372
+ 将当前拓扑图(节点和边)导出为 JSON 可序列化对象。
373
+
374
+ ```typescript
375
+ const data = topo.exportData();
376
+ // { nodes: Record<string, {x,y,z}>, edges: Array<{from,to,weight}> }
377
+ ```
378
+
379
+ 双向边在导出时会去重,只保留一条记录。
380
+
381
+ #### `importData(data: TopologyData)`
382
+
383
+ 从 `exportData()` 返回的数据中还原拓扑图,替换当前所有节点、边和路径网格,并重新渲染。
384
+
385
+ ```typescript
386
+ topo.importData(data);
387
+ ```
388
+
309
389
  #### `dispose()`
310
390
 
311
391
  清除图和路径网格。
@@ -2,9 +2,7 @@
2
2
 
3
3
  `u-space` 架构包含一套丰富的插件,提供从 GIS 瓦片加载到键盘控制和场景管理等高级功能。所有插件从 `u-space/plugins/*` 命名空间导入。
4
4
 
5
- ## 可用插件
6
-
7
- ### `keyboard-controls`
5
+ ## `keyboard-controls`
8
6
 
9
7
  为激活相机提供 WASD 或方向键的平移和旋转控制。
10
8
 
@@ -45,7 +43,7 @@ import { ACTION } from 'u-space/plugins/keyboard-controls';
45
43
  keyboardControls.keys['Space'] = ACTION.MOVE_UP;
46
44
  ```
47
45
 
48
- ### `minimap`
46
+ ## `minimap`
49
47
 
50
48
  生成一个 2D 小地图叠加层,在 3D 场景中跟踪目标对象。渲染到注入 `viewer.el` 的 `<canvas>` 元素中。
51
49
 
@@ -82,7 +80,7 @@ minimap.dispose();
82
80
  - `disable()` — 移除画布并停止渲染。
83
81
  - `dispose()` — 禁用并清理所有资源。
84
82
 
85
- ### `tiles`
83
+ ## `tiles`
86
84
 
87
85
  提供与 `3d-tiles-renderer` 和地理空间数据的集成。主要导出 `ArcgisTilesRenderer`,可流式加载 ArcGIS Online 3D 瓦片并将地球重新定向到指定地理位置。
88
86
 
@@ -109,7 +107,7 @@ arcgisTilesRenderer.enable();
109
107
  | `disable()` | 从场景中移除瓦片并暂停更新循环。 |
110
108
  | `dispose()` | 禁用并完全释放瓦片渲染器。 |
111
109
 
112
- ### `u-manager`
110
+ ## `u-manager`
113
111
 
114
112
  `u-manager` 是一套全面的加载器和解析器,用于从服务器路径流式传输、解密并显示结构化场景数据。支持场景、拓扑、动画、属性和相机视点。
115
113
 
@@ -233,7 +231,7 @@ const modelProps = properties.filter(p => p.modelId === myModel.userData.id);
233
231
  | `value` | `string \| null` | 属性值。 |
234
232
  | `label` | `string \| null` | 属性的显示标签。 |
235
233
 
236
- ### `curve-movement`
234
+ ## `curve-movement`
237
235
 
238
236
  沿样条路径对相机或对象进行动画。提供两个具体子类:`CurveMovementCamera` 和 `CurveMovementObject`。
239
237
 
@@ -272,7 +270,7 @@ movement.addEventListener('complete', () => console.log('完成'));
272
270
  | `positionOffset`| `Vector3` | `(0,0,0)` | 叠加到每个位置上的世界坐标偏移量。 |
273
271
  | `direction` | `1 \| -1` | `1` | 当前行进方向。 |
274
272
 
275
- ### `tracking-controls`
273
+ ## `tracking-controls`
276
274
 
277
275
  使相机平滑跟随移动的 `Object3D` 目标。
278
276
 
@@ -296,7 +294,7 @@ tracking.enable();
296
294
  | `type` | `'position' \| 'box3'` | `'position'` | 跟踪世界位置还是包围盒中心。 |
297
295
  | `offset` | `Vector3` | `(0,0,0)` | 在移动相机前叠加到跟踪位置上的偏移量。 |
298
296
 
299
- ### `atmosphere`
297
+ ## `atmosphere`
300
298
 
301
299
  天空和大气渲染插件。目前为占位实现,`enable()` / `disable()` / `dispose()` 方法可用,但尚未实现具体功能。
302
300
 
@@ -307,7 +305,7 @@ const atmosphere = new Atmosphere(viewer);
307
305
  atmosphere.enable();
308
306
  ```
309
307
 
310
- ### `object-controls`
308
+ ## `object-controls`
311
309
 
312
310
  对场景中的 3D 对象进行交互式移动、旋转、缩放操作。继承自 Three.js `TransformControls`,集成了 u-space `Viewer` 生命周期管理。
313
311
 
@@ -375,7 +373,7 @@ controls.addEventListener('dragging-changed', ({ value }) => {
375
373
 
376
374
  > 由于 `ObjectControls` 直接继承 `TransformControls`,所有原生属性(`translationSnap`、`rotationSnap`、`scaleSnap`、`showX/Y/Z` 等)和事件均可直接使用,参考 [Three.js TransformControls 文档](https://threejs.org/docs/#examples/en/controls/TransformControls)。
377
375
 
378
- ### `topology-drawer`
376
+ ## `topology-drawer`
379
377
 
380
378
  在 3D 场景中交互式绘制拓扑路径图。点击场景中的任意对象表面放置节点,自动连接成路径;点击空白处则落回不可见的地面平面。事件检测通过 `viewer.interactionManager` 实现(`scene.addEventListener` 冒泡)。
381
379
 
@@ -100,6 +100,52 @@ const camera = viewer.createOrthographicCamera();
100
100
  viewer.setCamera(camera);
101
101
  ```
102
102
 
103
+ ## 调试工具
104
+
105
+ ### Info
106
+
107
+ `viewer.info` 是一个轻量的渲染统计叠加层,显示当前帧的 GPU 诊断数据,适合开发调试阶段使用。
108
+
109
+ ```typescript
110
+ viewer.info.enable(); // 在画面左下角显示统计信息
111
+ viewer.info.disable(); // 隐藏统计信息
112
+ ```
113
+
114
+ 启用后将在 `viewer.el` 左下角叠加以下数据:
115
+
116
+ | 指标 | 说明 |
117
+ | :------------- | :---------------------------- |
118
+ | `draw calls` | 当前帧的绘制调用次数 |
119
+ | `frame calls` | 当前帧的帧调用次数 |
120
+ | `triangles` | 当前帧渲染的三角面数量 |
121
+ | `points` | 当前帧渲染的点数量 |
122
+ | `lines` | 当前帧渲染的线段数量 |
123
+ | `timestamp` | GPU 渲染耗时(ms,WebGPU 专属)|
124
+
125
+ > `timestamp` 指标仅在 WebGPU 后端可用,WebGL 回退模式下显示 `0`。
126
+
127
+ ### ViewerHelper
128
+
129
+ `viewer.viewerHelper` 是一个方向指示器 gizmo(基于 Three.js `ViewHelper`),显示当前相机朝向的 XYZ 轴,渲染为画面角落的叠加层。
130
+
131
+ ```typescript
132
+ viewer.viewerHelper.enable(); // 显示方向 gizmo
133
+ viewer.viewerHelper.disable(); // 隐藏方向 gizmo
134
+ ```
135
+
136
+ **属性:**
137
+
138
+ | 属性 | 类型 | 说明 |
139
+ | :------------- | :---------- | :---------------------------------------- |
140
+ | `location` | `object` | gizmo 在画面中的位置,支持 `top`、`bottom`、`left`、`right` 偏移(像素)。默认右下角。 |
141
+
142
+ ```typescript
143
+ // 调整位置到左下角
144
+ viewer.viewerHelper.location.left = 12;
145
+ viewer.viewerHelper.location.bottom = 12;
146
+ viewer.viewerHelper.location.right = null;
147
+ ```
148
+
103
149
  ### `dispose()`
104
150
 
105
151
  清理查看器,从 DOM 中移除 canvas,移除事件监听,并释放渲染器和环境贴图,以防止内存泄漏。
@@ -112,8 +158,10 @@ viewer.dispose();
112
158
 
113
159
  Viewer 继承自 `EventDispatcher`,会触发以下事件:
114
160
 
115
- - `beforeControlsUpdate`:在 `CameraControls` 更新之前触发,提供 `{ time: number }`。
116
- - `afterControlsUpdate`:在 `CameraControls` 更新之后触发,提供 `{ time: number }`。
117
- - `beforeRender`:在 `renderer.render` 调用之前立即触发,提供 `{ time: number }`。
118
- - `afterRender`:在 `renderer.render` 完成之后立即触发,提供 `{ time: number }`。
161
+ - `beforeControlsUpdate`:在 `CameraControls` 更新之前触发,提供 `{ time: number; delta: number }`。
162
+ - `afterControlsUpdate`:在 `CameraControls` 更新之后触发,提供 `{ time: number; delta: number }`。
163
+ - `beforeRender`:在 `renderer.render` 调用之前立即触发,提供 `{ time: number; delta: number }`。
164
+ - `afterRender`:在 `renderer.render` 完成之后立即触发,提供 `{ time: number; delta: number }`。
119
165
  - `cameraChange`:调用 `setCamera` 时触发,提供 `{ camera: Camera }`。
166
+
167
+ 其中 `delta` 为上一帧到当前帧的时间间隔(秒),可用于动画更新等场景。
@@ -46,3 +46,17 @@
46
46
  - 流式传输结构化场景布局,解析场景描述(`SceneLoader`、`TopologiesLoader`)。
47
47
  - 使用相机动画(`VisionsLoader` 和 `VisionsParser`)在场景中编排预定义的飞行路径。
48
48
  - 获取复杂的节点材质,并自定义 WebGPU 专属的 TSL(Three Shading Language)节点,如 `TSLEffects.fluid()`。
49
+
50
+ ## 5. `test_model_animation.html`:模型内置动画
51
+
52
+ [在线演示](https://u-space-phi.vercel.app/examples/test_model_animation.html)
53
+
54
+ 该示例演示了如何加载含内置动画的 glTF 模型,并通过 `Model` 类的动画 API 控制播放。
55
+
56
+ ### 核心要点:
57
+
58
+ - 使用 `Model.loadAsync()` 加载带动画的 `.glb` 文件,动画片段自动初始化。
59
+ - 使用 `viewer.frameloop = 'always'` 开启持续渲染以驱动动画。
60
+ - 监听 `beforeRender` 事件,通过 `model.updateAnimation(e.delta)` 推进动画时间。
61
+ - 使用 `model.playAnimation(name)` 按名称播放单个动画,`model.playAllAnimations()` 播放全部。
62
+ - 使用 `model.stopAnimation()` 停止动画播放。
@@ -93,8 +93,7 @@ pnpm install three camera-controls
93
93
  `u-space` 内置了 `InteractionManager`,可以轻松为 3D 对象添加事件监听。
94
94
 
95
95
  ```javascript
96
- // 启用指针移动事件
97
- viewer.interactionManager.targetObjects = [];
96
+ // 启用指针移动事件(pointerenter / pointerleave 需要此开关)
98
97
  viewer.interactionManager.pointerMoveEventsEnabled = true;
99
98
 
100
99
  // 添加点击事件
package/docs/index.md CHANGED
@@ -48,3 +48,5 @@ features:
48
48
  | [curve-movement](./api-plugins#curve-movement) | 沿样条曲线移动相机或对象 |
49
49
  | [tracking-controls](./api-plugins#tracking-controls) | 相机跟随移动目标 |
50
50
  | [atmosphere](./api-plugins#atmosphere) | 天空/大气渲染(开发中) |
51
+ | [object-controls](./api-plugins#object-controls) | 交互式移动、旋转、缩放 3D 对象 |
52
+ | [topology-drawer](./api-plugins#topology-drawer) | 在场景任意表面交互式绘制拓扑路径图 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u-space",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -29,7 +29,7 @@
29
29
  "docs:build": "vitepress build docs",
30
30
  "docs:preview": "vitepress preview docs",
31
31
  "docs:deploy": "pnpm docs:build && vercel --prod",
32
- "release": "npm publish --access=public"
32
+ "release": "npm version patch && npm publish --access=public"
33
33
  },
34
34
  "files": [
35
35
  "dist",