Appearance
Interactions API
InteractionManager 提供了一种统一的方式来处理 3D 场景中的用户输入(鼠标、触摸、指针)。它将屏幕空间的射线检测转换为世界空间坐标,并将对应事件直接分发到被命中的 3D 对象上。
InteractionManager 在 Viewer 内部自动实例化,可通过 viewer.interactionManager 访问。
对于三角形较多的静态模型,可以在模型加载后调用 enableMeshBVHRaycast(root)。该函数不会修改 Three.js 原型;它先保留每个 Mesh 的局部包围体粗筛,只有射线命中包围球后才为至少 10000 个三角形的 geometry 按需建立并复用 three-mesh-bvh。小几何、蒙皮、morph target 或自定义 raycast 对象会继续使用原始路径。
ts
import { enableMeshBVHRaycast } from 'u-space';
enableMeshBVHRaycast(loadedModel);启用交互事件
出于性能考虑,指针移动事件默认处于禁用状态。如需悬停和拖拽效果,必须显式开启。
typescript
// 启用鼠标移动事件(如 pointerenter 和 pointerleave)
viewer.interactionManager.pointerMoveEventsEnabled = true;目标对象
可以限制射线检测所针对的对象范围。默认值为 scene.children(即整个场景的直接子级,含递归嵌套)。 BaseMesh / BaseGroup 默认会在自身 visible === false 时让 raycast() 返回 false,从而阻止自身和子级继续参与递归射线检测;如需隐藏但仍可交互,可将对象的 ignoreInvisibleWhenRaycast 设为 false。setInteractable(object, false) / addIgnore(object) 会在命中后过滤该对象及其子对象。
typescript
// 仅检测指定对象
viewer.interactionManager.targetObjects = [myBox, myModel];
// 恢复默认:检测整个场景
viewer.interactionManager.targetObjects = viewer.scene.children;添加事件监听
由于 u-space 对象(以及继承自 BaseMesh、BaseGroup 的对象)支持自定义事件,你可以像操作 DOM 元素一样原生地绑定监听器。
typescript
const myBox = new Mesh(geometry, material);
viewer.scene.add(myBox);
// 直接在 Mesh 或 Model 上绑定监听器
myBox.addEventListener('click', (eventData) => {
// 底层指针事件和射线检测数据
const intersect = eventData.event.intersect;
console.log('点击位置:', intersect.point);
});支持的事件类型
以下事件类型可在可交互对象上监听:
click:指针点击对象时触发。内置智能过滤:长按(>500ms)或移动距离过大时忽略,双击时不重复触发。dblclick:快速双击对象时触发。rightclick:右键短按松开时触发(长按或拖拽不触发;浏览器原生上下文菜单已被阻止)。在pointerup时派发,因此可以正确过滤相机拖拽等操作。pointerdown:指针按键在对象上按下时触发。pointerup:指针按键在对象上释放时触发。pointermove:指针在对象上移动时触发,需要pointerMoveEventsEnabled = true。pointerenter:光标进入对象范围时触发,需要pointerMoveEventsEnabled = true。pointerleave:光标离开对象范围时触发,需要pointerMoveEventsEnabled = true。
事件冒泡
事件会沿父级链向上冒泡。若要阻止事件继续传播,可调用事件载荷上的 stopPropagation():
typescript
myObject.addEventListener('click', (e) => {
e.event.stopPropagation();
});InteractionEvent
传递给所有监听回调的事件对象,位于 event 键下。
属性
| 属性 | 类型 | 说明 |
|---|---|---|
type | InteractionEventType | 事件类型字符串(如 'click')。 |
target | Object3D | 触发事件的原始 3D 对象(第一个命中点)。 |
currentTarget | Object3D | 冒泡链中当前处理事件的对象。 |
intersect | Intersection | null | Three.js 射线检测数据:point、face、distance、uv 等。 |
originalEvent | PointerEvent | MouseEvent | 原始 DOM 指针/鼠标事件。 |
方法
stopPropagation()
阻止事件继续向上冒泡。
InteractionManager API
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
targetObjects | Object3D[] | scene.children | 射线检测的目标对象列表,默认为场景的直接子级。 |
pointerMoveEventsEnabled | boolean | false | 启用 pointermove、pointerenter、pointerleave 事件。 |
方法
enable() / disable()
全局启用或禁用所有交互事件。禁用后不再触发任何交互事件。
typescript
viewer.interactionManager.disable(); // 暂停交互
viewer.interactionManager.enable(); // 恢复交互setInteractable(object, interactable)
控制单个对象是否可交互。设为 false 后该对象及其所有子对象不再参与射线检测。
typescript
viewer.interactionManager.setInteractable(myModel, false); // 禁止交互
viewer.interactionManager.setInteractable(myModel, true); // 恢复交互addIgnore(object) / removeIgnore(object)
setInteractable 的别名。addIgnore(obj) 等同于 setInteractable(obj, false),removeIgnore(obj) 等同于 setInteractable(obj, true)。
typescript
viewer.interactionManager.addIgnore(helperObject); // 忽略辅助对象
viewer.interactionManager.removeIgnore(helperObject); // 恢复setCamera(camera)
更新用于射线检测的相机。由 viewer.setCamera() 自动调用。
dispose()
移除所有 DOM 事件监听,清理内部状态。
typescript
viewer.interactionManager.dispose();Selection
Selection 提供对象选择能力,包括单选、多选、toggle 和框选(rubber-band)。
typescript
import { Selection } from 'u-space';
const selection = new Selection(viewer.renderer.domElement, viewer.scene, viewer.camera);基础选择
typescript
selection.select(myObject); // 选中
selection.select([obj1, obj2]); // 多选
selection.deselect(myObject); // 取消选择
selection.toggle(myObject); // 切换选择状态
selection.clear(); // 清空选择
selection.isSelected(myObject); // 检查是否已选属性
| 属性 | 类型 | 说明 |
|---|---|---|
selected | Set<Object3D> | 当前已选对象集合。 |
selectedArray | Object3D[] | 当前已选对象数组。 |
targetObjects | Object3D[] | 框选时的候选对象(默认为场景子级)。 |
框选
启用后可用鼠标拖动矩形区域选择多个对象。框选覆盖层会渲染在容器元素上。
typescript
selection.enableBoxSelection({ deep: true }); // 开启框选
selection.disableBoxSelection(); // 关闭框选BoxSelectionOptions
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
className | string | — | 框选矩形的 CSS 类名。 |
deep | boolean | true | 是否递归检测子对象。 |
事件
typescript
selection.addEventListener('select', (e) => {
console.log('新选中:', e.objects);
});
selection.addEventListener('deselect', (e) => {
console.log('取消选中:', e.objects);
});
selection.addEventListener('change', (e) => {
console.log('当前选中:', e.selected.size, '个对象');
});方法
setCamera(camera)
更新用于框选投影计算的相机。切换相机时需调用。
dispose()
关闭框选、移除事件监听、清空选择集。