u-space 0.0.7 → 0.0.9
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.cjs +16 -1
- package/dist/index.js +1578 -534
- package/dist/src/effects/MaterialEffects.d.ts +23 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/interactions/InteractionManager.d.ts +31 -0
- package/dist/src/interactions/Selection.d.ts +77 -0
- package/dist/src/interactions/index.d.ts +1 -0
- package/dist/src/managers/LightManager.d.ts +101 -0
- package/dist/src/managers/ObjectManager.d.ts +33 -1
- package/dist/src/managers/SceneManager.d.ts +57 -0
- package/dist/src/managers/index.d.ts +2 -0
- package/dist/src/objects/Model.d.ts +13 -1
- package/dist/src/tools/AnnotationManager.d.ts +104 -0
- package/dist/src/tools/ClippingTool.d.ts +96 -0
- package/dist/src/tools/MeasureTool.d.ts +80 -0
- package/dist/src/tools/index.d.ts +3 -0
- package/dist/src/viewers/CameraControls.d.ts +23 -0
- package/dist/src/viewers/Viewer.d.ts +52 -1
- package/docs/api-camera-controls.md +146 -0
- package/docs/api-effects.md +47 -5
- package/docs/api-interactions.md +107 -7
- package/docs/api-managers.md +181 -0
- package/docs/api-objects.md +46 -13
- package/docs/api-plugin-atmosphere.md +10 -0
- package/docs/api-plugin-curve-movement.md +38 -0
- package/docs/api-plugin-keyboard-controls.md +40 -0
- package/docs/api-plugin-minimap.md +36 -0
- package/docs/api-plugin-object-controls.md +67 -0
- package/docs/api-plugin-tiles.md +26 -0
- package/docs/api-plugin-topology-drawer.md +74 -0
- package/docs/api-plugin-tracking-controls.md +23 -0
- package/docs/api-plugin-u-manager.md +123 -0
- package/docs/api-tools.md +254 -0
- package/docs/api-viewer.md +85 -19
- package/docs/changelog.md +105 -0
- package/docs/examples-guide.md +104 -0
- package/docs/getting-started.md +1 -1
- package/docs/index.md +14 -12
- package/package.json +1 -1
- package/docs/api-plugins.md +0 -449
|
@@ -9,6 +9,9 @@ export interface FlyToBoxOptions {
|
|
|
9
9
|
}
|
|
10
10
|
export interface FlyToObjectOptions extends FlyToBoxOptions {
|
|
11
11
|
}
|
|
12
|
+
export interface FlyToOptions {
|
|
13
|
+
enableTransition?: boolean;
|
|
14
|
+
}
|
|
12
15
|
export interface CameraViewpointData {
|
|
13
16
|
position: IVector3;
|
|
14
17
|
target: IVector3;
|
|
@@ -22,5 +25,25 @@ export declare class CameraControls extends CameraControlsBase {
|
|
|
22
25
|
absoluteRotations(): void;
|
|
23
26
|
flyToBox(box: Box3, options?: FlyToBoxOptions): Promise<boolean>;
|
|
24
27
|
flyToObject(object: Object3D, options?: FlyToObjectOptions): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Fly camera to a specific position and look-at target.
|
|
30
|
+
*/
|
|
31
|
+
flyTo(position: IVector3, target: IVector3, options?: FlyToOptions): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Get the current camera viewpoint data (position, target, zoom).
|
|
34
|
+
*/
|
|
35
|
+
getCameraViewpoint(): CameraViewpointData;
|
|
36
|
+
/**
|
|
37
|
+
* Lock camera controls (disable all user interaction).
|
|
38
|
+
*/
|
|
39
|
+
lock(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Unlock camera controls (re-enable user interaction).
|
|
42
|
+
*/
|
|
43
|
+
unlock(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Switch between 2D top-down and 3D perspective views.
|
|
46
|
+
*/
|
|
47
|
+
setViewMode(mode: '2d' | '3d', enableTransition?: boolean): Promise<void>;
|
|
25
48
|
setCameraViewpoint(viewpoint: CameraViewpointData, enableTransition?: boolean): Promise<[void, void]>;
|
|
26
49
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventDispatcher, WebGPURenderer, Scene, PerspectiveCamera, Timer, OrthographicCamera } from 'three/webgpu';
|
|
1
|
+
import { EventDispatcher, WebGPURenderer, Scene, PerspectiveCamera, Timer, OrthographicCamera, type ColorRepresentation, type Texture } from 'three/webgpu';
|
|
2
2
|
import { InteractionManager } from '../interactions';
|
|
3
3
|
import { ObjectManager } from '../managers';
|
|
4
4
|
import { RenderPipeline } from './RenderPipeline';
|
|
@@ -12,6 +12,21 @@ export interface ViewerOptions {
|
|
|
12
12
|
el: HTMLElement;
|
|
13
13
|
rendererOptions?: ViewerRendererOptions;
|
|
14
14
|
}
|
|
15
|
+
export interface ScreenshotOptions {
|
|
16
|
+
width?: number;
|
|
17
|
+
height?: number;
|
|
18
|
+
type?: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
19
|
+
quality?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface FogOptions {
|
|
22
|
+
color?: ColorRepresentation;
|
|
23
|
+
near?: number;
|
|
24
|
+
far?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface FogExp2Options {
|
|
27
|
+
color?: ColorRepresentation;
|
|
28
|
+
density?: number;
|
|
29
|
+
}
|
|
15
30
|
export interface ViewerEventMap {
|
|
16
31
|
beforeControlsUpdate: {
|
|
17
32
|
time: number;
|
|
@@ -60,6 +75,42 @@ declare class Viewer extends EventDispatcher<ViewerEventMap> {
|
|
|
60
75
|
createScene(): Scene;
|
|
61
76
|
createPerspectiveCamera(): PerspectiveCamera;
|
|
62
77
|
createOrthographicCamera(): OrthographicCamera;
|
|
78
|
+
/**
|
|
79
|
+
* Manually trigger a resize update.
|
|
80
|
+
*/
|
|
81
|
+
resize(width?: number, height?: number): void;
|
|
82
|
+
/**
|
|
83
|
+
* Capture a screenshot of the current render.
|
|
84
|
+
*/
|
|
85
|
+
screenshot(options?: ScreenshotOptions): Promise<string>;
|
|
86
|
+
/**
|
|
87
|
+
* Set the scene background color, texture, or null.
|
|
88
|
+
*/
|
|
89
|
+
setBackground(background: ColorRepresentation | Texture | null): void;
|
|
90
|
+
/**
|
|
91
|
+
* Set the scene environment map for reflections / IBL.
|
|
92
|
+
*/
|
|
93
|
+
setEnvironment(envMap: Texture | null): void;
|
|
94
|
+
/**
|
|
95
|
+
* Enable shadow rendering.
|
|
96
|
+
*/
|
|
97
|
+
enableShadow(): void;
|
|
98
|
+
/**
|
|
99
|
+
* Disable shadow rendering.
|
|
100
|
+
*/
|
|
101
|
+
disableShadow(): void;
|
|
102
|
+
/**
|
|
103
|
+
* Enable linear fog.
|
|
104
|
+
*/
|
|
105
|
+
enableFog(options?: FogOptions): void;
|
|
106
|
+
/**
|
|
107
|
+
* Enable exponential fog.
|
|
108
|
+
*/
|
|
109
|
+
enableFogExp2(options?: FogExp2Options): void;
|
|
110
|
+
/**
|
|
111
|
+
* Disable fog.
|
|
112
|
+
*/
|
|
113
|
+
disableFog(): void;
|
|
63
114
|
dispose(): void;
|
|
64
115
|
}
|
|
65
116
|
export { Viewer };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# CameraControls API
|
|
2
|
+
|
|
3
|
+
`CameraControls` 是 `u-space` 对 [`camera-controls`](https://github.com/yomotsu/camera-controls) 库的扩展封装,提供相机飞行、视角切换等高级功能。通过 `viewer.controls` 访问。
|
|
4
|
+
|
|
5
|
+
## 默认配置
|
|
6
|
+
|
|
7
|
+
| 属性 | 默认值 | 说明 |
|
|
8
|
+
| :------------ | :----- | :----------------------------- |
|
|
9
|
+
| `minDistance` | `0.2` | 相机最小缩放距离。 |
|
|
10
|
+
| `smoothTime` | `0.2` | 平滑过渡时间(秒)。 |
|
|
11
|
+
| `dollySpeed` | `0.2` | 滚轮缩放速度。 |
|
|
12
|
+
|
|
13
|
+
> 更多基础属性和方法请参考 [camera-controls 文档](https://github.com/yomotsu/camera-controls)。
|
|
14
|
+
|
|
15
|
+
## 方法
|
|
16
|
+
|
|
17
|
+
### `flyToBox(box, options?)`
|
|
18
|
+
|
|
19
|
+
将相机飞行到指定的 `Box3` 包围盒。
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { Box3 } from 'three/webgpu';
|
|
23
|
+
|
|
24
|
+
const box = new Box3().setFromObject(myModel);
|
|
25
|
+
await viewer.controls.flyToBox(box, {
|
|
26
|
+
viewpoint: 'frontTop',
|
|
27
|
+
enableTransition: true,
|
|
28
|
+
padding: 0.1,
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
#### `FlyToBoxOptions`
|
|
33
|
+
|
|
34
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
35
|
+
| :----------------- | :-------- | :----------- | :------------------------------------------------ |
|
|
36
|
+
| `viewpoint` | `string` | `'frontTop'` | 预设视角方向,见下方视角列表。设为 `'current'` 保持当前朝向。 |
|
|
37
|
+
| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |
|
|
38
|
+
| `padding` | `number` | `0.1` | 包围盒四周的留白比例。 |
|
|
39
|
+
| `cover` | `boolean` | `false` | 是否以覆盖模式适配(类似 CSS `object-fit: cover`)。 |
|
|
40
|
+
|
|
41
|
+
**预设视角:**
|
|
42
|
+
|
|
43
|
+
`top` | `bottom` | `front` | `back` | `left` | `right` | `frontTop` | `backTop` | `leftTop` | `rightTop` | `leftFrontTop` | `rightFrontTop` | `leftBackTop` | `rightBackTop` | `current`
|
|
44
|
+
|
|
45
|
+
### `flyToObject(object, options?)`
|
|
46
|
+
|
|
47
|
+
将相机飞行到指定对象的包围盒。参数同 `flyToBox`。
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
await viewer.controls.flyToObject(myModel, { viewpoint: 'rightFrontTop' });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `setCameraViewpoint(viewpoint, enableTransition?)`
|
|
54
|
+
|
|
55
|
+
将相机平滑过渡到指定的位置、目标和缩放。
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
await viewer.controls.setCameraViewpoint({
|
|
59
|
+
position: { x: 10, y: 5, z: 10 },
|
|
60
|
+
target: { x: 0, y: 0, z: 0 },
|
|
61
|
+
zoom: 1.0,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// 禁用过渡动画,立即跳转
|
|
65
|
+
await viewer.controls.setCameraViewpoint(viewpoint, false);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**参数:**
|
|
69
|
+
|
|
70
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
71
|
+
| :----------------- | :--------------------- | :------ | :---------------------------------- |
|
|
72
|
+
| `viewpoint` | `CameraViewpointData` | — | 包含 `position`、`target`、`zoom`。 |
|
|
73
|
+
| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |
|
|
74
|
+
|
|
75
|
+
#### `CameraViewpointData`
|
|
76
|
+
|
|
77
|
+
| 属性 | 类型 | 说明 |
|
|
78
|
+
| :--------- | :--------- | :------------------- |
|
|
79
|
+
| `position` | `IVector3` | 相机位置。 |
|
|
80
|
+
| `target` | `IVector3` | 相机注视目标位置。 |
|
|
81
|
+
| `zoom` | `number` | 相机缩放值。 |
|
|
82
|
+
|
|
83
|
+
### `flyTo(position, target, options?)`
|
|
84
|
+
|
|
85
|
+
将相机飞行到指定的位置和注视目标。
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
await viewer.controls.flyTo(
|
|
89
|
+
{ x: 10, y: 8, z: 10 },
|
|
90
|
+
{ x: 0, y: 0, z: 0 },
|
|
91
|
+
{ enableTransition: true },
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**参数:**
|
|
96
|
+
|
|
97
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
98
|
+
| :----------------- | :--------- | :----- | :---------------------- |
|
|
99
|
+
| `position` | `IVector3` | — | 相机目标位置。 |
|
|
100
|
+
| `target` | `IVector3` | — | 相机注视目标。 |
|
|
101
|
+
| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |
|
|
102
|
+
|
|
103
|
+
### `getCameraViewpoint()`
|
|
104
|
+
|
|
105
|
+
获取当前相机的视角数据,返回 `CameraViewpointData`。与 `setCameraViewpoint` 对应,方便保存/恢复视角。
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const viewpoint = viewer.controls.getCameraViewpoint();
|
|
109
|
+
console.log(viewpoint.position, viewpoint.target, viewpoint.zoom);
|
|
110
|
+
|
|
111
|
+
// 稍后恢复
|
|
112
|
+
await viewer.controls.setCameraViewpoint(viewpoint);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `lock()` / `unlock()`
|
|
116
|
+
|
|
117
|
+
锁定或解锁相机控制(禁用/启用所有用户交互)。
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
viewer.controls.lock(); // 禁止用户操作相机
|
|
121
|
+
viewer.controls.unlock(); // 恢复用户操作
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `setViewMode(mode, enableTransition?)`
|
|
125
|
+
|
|
126
|
+
在 2D 俯视图和 3D 透视图之间切换。2D 模式会将相机旋转到正上方,并锁定极角。
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
await viewer.controls.setViewMode('2d'); // 切换到 2D 俯视模式
|
|
130
|
+
await viewer.controls.setViewMode('3d'); // 切换回 3D 模式
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**参数:**
|
|
134
|
+
|
|
135
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
136
|
+
| :----------------- | :---------------- | :----- | :---------------------- |
|
|
137
|
+
| `mode` | `'2d'` \| `'3d'` | — | 视图模式。 |
|
|
138
|
+
| `enableTransition` | `boolean` | `true` | 是否启用平滑过渡动画。 |
|
|
139
|
+
|
|
140
|
+
### `absoluteRotations()`
|
|
141
|
+
|
|
142
|
+
将方位角(azimuth)归一化到 `[-π, π]` 范围内,避免相机在飞行过渡时产生多余旋转。在 `flyToBox` 内部自动调用。
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
viewer.controls.absoluteRotations();
|
|
146
|
+
```
|
package/docs/api-effects.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
特性:
|
|
10
10
|
- **效果可叠加**:高亮和呼吸效果可同时作用于同一对象,呼吸在高亮结果之上混合
|
|
11
11
|
- **共享材质安全**:按材质跟踪引用计数,多个 Mesh 共享材质时互不干扰
|
|
12
|
-
- **完整还原**:移除效果时自动恢复材质原始的 `colorNode`、`opacityNode` 和 `
|
|
12
|
+
- **完整还原**:移除效果时自动恢复材质原始的 `colorNode`、`opacityNode`、`transparent` 和 `depthWrite` 状态
|
|
13
13
|
|
|
14
14
|
### `MaterialEffects.highlightColor(object, options?)`
|
|
15
15
|
|
|
@@ -18,13 +18,24 @@
|
|
|
18
18
|
```typescript
|
|
19
19
|
import { MaterialEffects } from 'u-space';
|
|
20
20
|
|
|
21
|
-
// 以 50%
|
|
21
|
+
// 以 50% 透明度高亮为红色(叠加模式)
|
|
22
22
|
MaterialEffects.highlightColor(myModel, {
|
|
23
23
|
color: 0xff0000,
|
|
24
24
|
opacity: 0.5,
|
|
25
25
|
overwrite: false, // false = 叠加(相乘),true = 完全替换颜色
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
// 半透明效果
|
|
29
|
+
MaterialEffects.highlightColor(myModel, { opacity: 0.3 });
|
|
30
|
+
|
|
31
|
+
// X 光效果(替换颜色 + 关闭深度写入)
|
|
32
|
+
MaterialEffects.highlightColor(myModel, {
|
|
33
|
+
color: 0x0088ff,
|
|
34
|
+
opacity: 0.25,
|
|
35
|
+
overwrite: true,
|
|
36
|
+
depthWrite: false,
|
|
37
|
+
});
|
|
38
|
+
|
|
28
39
|
// 支持数组
|
|
29
40
|
MaterialEffects.highlightColor([model1, model2], { color: 0x00ff00 });
|
|
30
41
|
```
|
|
@@ -33,9 +44,10 @@ MaterialEffects.highlightColor([model1, model2], { color: 0x00ff00 });
|
|
|
33
44
|
|
|
34
45
|
| 属性 | 类型 | 默认值 | 说明 |
|
|
35
46
|
| :---------- | :-------------------- | :---------- | :--------------------------------------------------------------------------- |
|
|
36
|
-
| `color`
|
|
37
|
-
| `opacity`
|
|
38
|
-
| `overwrite`
|
|
47
|
+
| `color` | `ColorRepresentation` | `0xff0000` | 高亮颜色。 |
|
|
48
|
+
| `opacity` | `number` | `0.5` | 高亮时材质的透明度。 |
|
|
49
|
+
| `overwrite` | `boolean` | `false` | `false` = 与原始颜色相乘(叠加);`true` = 完全替换颜色。 |
|
|
50
|
+
| `depthWrite` | `boolean` | — | 可选。设为 `false` 可产生 X 光透视效果。不设置时保持原始值。 |
|
|
39
51
|
|
|
40
52
|
### `MaterialEffects.removeHighlightColor(object)`
|
|
41
53
|
|
|
@@ -74,6 +86,36 @@ viewer.frameloop = 'always';
|
|
|
74
86
|
MaterialEffects.removeBreatheColor(myModel);
|
|
75
87
|
```
|
|
76
88
|
|
|
89
|
+
### `MaterialEffects.wireframe(object, enabled?)`
|
|
90
|
+
|
|
91
|
+
开启或关闭线框渲染模式。
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
MaterialEffects.wireframe(myModel); // 开启线框
|
|
95
|
+
MaterialEffects.wireframe(myModel, false); // 关闭线框
|
|
96
|
+
MaterialEffects.removeWireframe(myModel); // 等同于 wireframe(obj, false)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### `MaterialEffects.fadeIn(object, options?)` / `MaterialEffects.fadeOut(object, options?)`
|
|
100
|
+
|
|
101
|
+
淡入/淡出动画效果。返回 `Promise`,在动画完成后 resolve。淡出后对象材质保持透明状态。
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// 淡出
|
|
105
|
+
await MaterialEffects.fadeOut(myModel, { duration: 1000 });
|
|
106
|
+
|
|
107
|
+
// 淡入
|
|
108
|
+
await MaterialEffects.fadeIn(myModel, { duration: 500 });
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
> 动画期间需要持续渲染,建议配合 `viewer.frameloop = 'always'` 使用。
|
|
112
|
+
|
|
113
|
+
#### `FadeOptions`
|
|
114
|
+
|
|
115
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
116
|
+
| :--------- | :------- | :----- | :------------------ |
|
|
117
|
+
| `duration` | `number` | `500` | 动画时长(毫秒)。 |
|
|
118
|
+
|
|
77
119
|
---
|
|
78
120
|
|
|
79
121
|
## `TSLEffects`
|
package/docs/api-interactions.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## 启用交互事件
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
出于性能考虑,指针移动事件默认处于禁用状态。如需悬停和拖拽效果,必须显式开启。
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
// 启用鼠标移动事件(如 pointerenter 和 pointerleave)
|
|
@@ -46,9 +46,9 @@ myBox.addEventListener('click', (eventData) => {
|
|
|
46
46
|
|
|
47
47
|
以下事件类型可在可交互对象上监听:
|
|
48
48
|
|
|
49
|
-
- `click
|
|
49
|
+
- `click`:指针点击对象时触发。内置智能过滤:长按(>500ms)或移动距离过大时忽略,双击时不重复触发。
|
|
50
50
|
- `dblclick`:快速双击对象时触发。
|
|
51
|
-
- `rightclick
|
|
51
|
+
- `rightclick`:右键短按松开时触发(长按或拖拽不触发;浏览器原生上下文菜单已被阻止)。在 `pointerup` 时派发,因此可以正确过滤相机拖拽等操作。
|
|
52
52
|
- `pointerdown`:指针按键在对象上按下时触发。
|
|
53
53
|
- `pointerup`:指针按键在对象上释放时触发。
|
|
54
54
|
- `pointermove`:指针在对象上移动时触发,需要 `pointerMoveEventsEnabled = true`。
|
|
@@ -89,13 +89,40 @@ myObject.addEventListener('click', (e) => {
|
|
|
89
89
|
|
|
90
90
|
### 属性
|
|
91
91
|
|
|
92
|
-
| 属性 | 类型 | 默认值
|
|
93
|
-
| :------------------------- | :---------------------------- |
|
|
94
|
-
| `targetObjects` | `Object3D[]` | `scene.children`
|
|
95
|
-
| `pointerMoveEventsEnabled` | `boolean` | `false`
|
|
92
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
93
|
+
| :------------------------- | :---------------------------- | :---------------- | :--------------------------------------------------------- |
|
|
94
|
+
| `targetObjects` | `Object3D[]` | `scene.children` | 射线检测的目标对象列表,默认为场景的直接子级。 |
|
|
95
|
+
| `pointerMoveEventsEnabled` | `boolean` | `false` | 启用 `pointermove`、`pointerenter`、`pointerleave` 事件。 |
|
|
96
96
|
|
|
97
97
|
### 方法
|
|
98
98
|
|
|
99
|
+
#### `enable()` / `disable()`
|
|
100
|
+
|
|
101
|
+
全局启用或禁用所有交互事件。禁用后不再触发任何交互事件。
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
viewer.interactionManager.disable(); // 暂停交互
|
|
105
|
+
viewer.interactionManager.enable(); // 恢复交互
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### `setInteractable(object, interactable)`
|
|
109
|
+
|
|
110
|
+
控制单个对象是否可交互。设为 `false` 后该对象及其所有子对象不再参与射线检测。
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
viewer.interactionManager.setInteractable(myModel, false); // 禁止交互
|
|
114
|
+
viewer.interactionManager.setInteractable(myModel, true); // 恢复交互
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### `addIgnore(object)` / `removeIgnore(object)`
|
|
118
|
+
|
|
119
|
+
`setInteractable` 的别名。`addIgnore(obj)` 等同于 `setInteractable(obj, false)`,`removeIgnore(obj)` 等同于 `setInteractable(obj, true)`。
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
viewer.interactionManager.addIgnore(helperObject); // 忽略辅助对象
|
|
123
|
+
viewer.interactionManager.removeIgnore(helperObject); // 恢复
|
|
124
|
+
```
|
|
125
|
+
|
|
99
126
|
#### `setCamera(camera)`
|
|
100
127
|
|
|
101
128
|
更新用于射线检测的相机。由 `viewer.setCamera()` 自动调用。
|
|
@@ -107,3 +134,76 @@ myObject.addEventListener('click', (e) => {
|
|
|
107
134
|
```typescript
|
|
108
135
|
viewer.interactionManager.dispose();
|
|
109
136
|
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Selection
|
|
141
|
+
|
|
142
|
+
`Selection` 提供对象选择能力,包括单选、多选、toggle 和框选(rubber-band)。
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { Selection } from 'u-space';
|
|
146
|
+
|
|
147
|
+
const selection = new Selection(viewer.renderer.domElement, viewer.scene, viewer.camera);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 基础选择
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
selection.select(myObject); // 选中
|
|
154
|
+
selection.select([obj1, obj2]); // 多选
|
|
155
|
+
selection.deselect(myObject); // 取消选择
|
|
156
|
+
selection.toggle(myObject); // 切换选择状态
|
|
157
|
+
selection.clear(); // 清空选择
|
|
158
|
+
selection.isSelected(myObject); // 检查是否已选
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 属性
|
|
162
|
+
|
|
163
|
+
| 属性 | 类型 | 说明 |
|
|
164
|
+
| :-------------- | :-------------- | :---------------------------------- |
|
|
165
|
+
| `selected` | `Set<Object3D>` | 当前已选对象集合。 |
|
|
166
|
+
| `selectedArray` | `Object3D[]` | 当前已选对象数组。 |
|
|
167
|
+
| `targetObjects` | `Object3D[]` | 框选时的候选对象(默认为场景子级)。 |
|
|
168
|
+
|
|
169
|
+
### 框选
|
|
170
|
+
|
|
171
|
+
启用后可用鼠标拖动矩形区域选择多个对象。框选覆盖层会渲染在容器元素上。
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
selection.enableBoxSelection({ deep: true }); // 开启框选
|
|
175
|
+
selection.disableBoxSelection(); // 关闭框选
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### `BoxSelectionOptions`
|
|
179
|
+
|
|
180
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
181
|
+
| :---------- | :-------- | :----- | :------------------------------ |
|
|
182
|
+
| `className` | `string` | — | 框选矩形的 CSS 类名。 |
|
|
183
|
+
| `deep` | `boolean` | `true` | 是否递归检测子对象。 |
|
|
184
|
+
|
|
185
|
+
### 事件
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
selection.addEventListener('select', (e) => {
|
|
189
|
+
console.log('新选中:', e.objects);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
selection.addEventListener('deselect', (e) => {
|
|
193
|
+
console.log('取消选中:', e.objects);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
selection.addEventListener('change', (e) => {
|
|
197
|
+
console.log('当前选中:', e.selected.size, '个对象');
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 方法
|
|
202
|
+
|
|
203
|
+
#### `setCamera(camera)`
|
|
204
|
+
|
|
205
|
+
更新用于框选投影计算的相机。切换相机时需调用。
|
|
206
|
+
|
|
207
|
+
#### `dispose()`
|
|
208
|
+
|
|
209
|
+
关闭框选、移除事件监听、清空选择集。
|
package/docs/api-managers.md
CHANGED
|
@@ -98,8 +98,189 @@ viewer.objectManager.removeByName('sedan');
|
|
|
98
98
|
viewer.objectManager.removeByType('Model');
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
### 显隐控制
|
|
102
|
+
|
|
103
|
+
#### `show(id: string)` / `hide(id: string)`
|
|
104
|
+
|
|
105
|
+
控制对象的可见性。
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
viewer.objectManager.hide('car-01');
|
|
109
|
+
viewer.objectManager.show('car-01');
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### `isolate(ids: string[])`
|
|
113
|
+
|
|
114
|
+
孤立显示:仅显示指定 ID 的对象,隐藏其余所有。
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
viewer.objectManager.isolate(['car-01', 'car-02']);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### `showAll()`
|
|
121
|
+
|
|
122
|
+
恢复显示所有已管理对象。
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
viewer.objectManager.showAll();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 材质操作
|
|
129
|
+
|
|
130
|
+
#### `setOpacity(id: string, opacity: number)`
|
|
131
|
+
|
|
132
|
+
设置指定对象所有材质的透明度。
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
viewer.objectManager.setOpacity('building-01', 0.3);
|
|
136
|
+
viewer.objectManager.setOpacity('building-01', 1.0); // 恢复不透明
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 空间查询
|
|
140
|
+
|
|
141
|
+
#### `getBoundingBox(id?: string)`
|
|
142
|
+
|
|
143
|
+
获取指定对象的包围盒,不传 `id` 则返回所有已管理对象的包围盒。
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
const box = viewer.objectManager.getBoundingBox('car-01');
|
|
147
|
+
const allBox = viewer.objectManager.getBoundingBox(); // 全部对象
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 遍历与过滤
|
|
151
|
+
|
|
152
|
+
#### `forEach(callback)`
|
|
153
|
+
|
|
154
|
+
遍历所有已管理对象。
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
viewer.objectManager.forEach((object, ids) => {
|
|
158
|
+
console.log(`对象: ${object.name}, IDs: ${Array.from(ids).join(', ')}`);
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### `filter(predicate)`
|
|
163
|
+
|
|
164
|
+
按条件过滤对象,返回匹配的数组。
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const cars = viewer.objectManager.filter((obj) => obj.name.startsWith('car'));
|
|
168
|
+
```
|
|
169
|
+
|
|
101
170
|
### 工具方法
|
|
102
171
|
|
|
103
172
|
- `getAll()`:返回所有已跟踪对象的 `Set<Object3D>`。
|
|
104
173
|
- `clear()`:从所有内部映射中移除所有对象。
|
|
105
174
|
- `size`:返回当前管理器跟踪的唯一对象总数。
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## SceneManager
|
|
179
|
+
|
|
180
|
+
`SceneManager` 用于管理多个场景的创建、注册、切换和序列化。
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { SceneManager } from 'u-space';
|
|
184
|
+
|
|
185
|
+
const sceneManager = new SceneManager();
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 方法
|
|
189
|
+
|
|
190
|
+
#### `create(key, options?)`
|
|
191
|
+
|
|
192
|
+
创建并注册一个新场景。
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const scene = sceneManager.create('indoor', { background: 0x333333 });
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### `add(key, scene)` / `get(key)` / `remove(key)`
|
|
199
|
+
|
|
200
|
+
手动注册、获取或移除场景。
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
sceneManager.add('outdoor', existingScene);
|
|
204
|
+
const scene = sceneManager.get('outdoor');
|
|
205
|
+
sceneManager.remove('outdoor');
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### `serialize(key)`
|
|
209
|
+
|
|
210
|
+
将场景元数据序列化为 JSON 快照。
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
const snapshot = sceneManager.serialize('indoor');
|
|
214
|
+
// { name, background, environmentRotation, children }
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### `keys()` / `size` / `clear()`
|
|
218
|
+
|
|
219
|
+
列出所有场景 key、获取场景数量或清空。
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## LightManager
|
|
224
|
+
|
|
225
|
+
`LightManager` 提供灯光的便捷创建、预设和 Helper 可视化。
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
import { LightManager } from 'u-space';
|
|
229
|
+
|
|
230
|
+
const lightManager = new LightManager(viewer.scene);
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### 灯光创建
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
lightManager.addAmbient('ambient', { color: 0xffffff, intensity: 0.5 });
|
|
237
|
+
lightManager.addDirectional('sun', { position: { x: 5, y: 10, z: 5 }, castShadow: true });
|
|
238
|
+
lightManager.addPoint('bulb', { position: { x: 0, y: 3, z: 0 }, intensity: 2 });
|
|
239
|
+
lightManager.addSpot('spot', { position: { x: 0, y: 10, z: 0 }, angle: Math.PI / 6 });
|
|
240
|
+
lightManager.addHemisphere('hemi', { skyColor: 0x87ceeb, groundColor: 0x362907 });
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 灯光预设
|
|
244
|
+
|
|
245
|
+
一键应用常见场景的灯光配置:
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
lightManager.applyPreset('indoor'); // 室内:环境光 + 顶部点光源
|
|
249
|
+
lightManager.applyPreset('outdoor'); // 室外:半球光 + 方向光(阳光)
|
|
250
|
+
lightManager.applyPreset('studio'); // 摄影棚:三点布光
|
|
251
|
+
lightManager.applyPreset('warehouse'); // 仓库:多点光源照明
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
| 预设 | 配置 |
|
|
255
|
+
| :---------- | :-------------------------------------- |
|
|
256
|
+
| `indoor` | 环境光 + 2 个点光源 |
|
|
257
|
+
| `outdoor` | 半球光 + 方向光(带阴影) |
|
|
258
|
+
| `studio` | 环境光 + 主光 + 补光 + 轮廓光 |
|
|
259
|
+
| `warehouse` | 环境光 + 4 个点光源(四角分布) |
|
|
260
|
+
|
|
261
|
+
### Helper 可视化
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
lightManager.showHelper('sun'); // 显示单个灯光 Helper(默认 size=5, color=0xff0000)
|
|
265
|
+
lightManager.showHelper('sun', 2, 0x00ff00); // 自定义尺寸和颜色
|
|
266
|
+
lightManager.showAllHelpers(); // 显示所有灯光 Helper
|
|
267
|
+
lightManager.hideHelper('sun'); // 隐藏单个
|
|
268
|
+
lightManager.hideAllHelpers(); // 隐藏所有
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### `showHelper(id, size?, color?)`
|
|
272
|
+
|
|
273
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
274
|
+
| :------ | :-------------------- | :---------- | :---------------- |
|
|
275
|
+
| `id` | `string` | — | 灯光 ID。 |
|
|
276
|
+
| `size` | `number` | `5` | Helper 尺寸。 |
|
|
277
|
+
| `color` | `ColorRepresentation` | `0xff0000` | Helper 颜色。 |
|
|
278
|
+
|
|
279
|
+
### 管理
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
lightManager.get('sun'); // 获取灯光
|
|
283
|
+
lightManager.remove('sun'); // 移除灯光
|
|
284
|
+
lightManager.removeAll(); // 移除所有
|
|
285
|
+
lightManager.dispose(); // 清理
|
|
286
|
+
```
|