Skip to content

Interactions API

InteractionManager 提供了一种统一的方式来处理 3D 场景中的用户输入(鼠标、触摸、指针)。它将屏幕空间的射线检测转换为世界空间坐标,并将对应事件直接分发到被命中的 3D 对象上。

InteractionManagerViewer 内部自动实例化,可通过 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 设为 falsesetInteractable(object, false) / addIgnore(object) 会在命中后过滤该对象及其子对象。

typescript
// 仅检测指定对象
viewer.interactionManager.targetObjects = [myBox, myModel];

// 恢复默认:检测整个场景
viewer.interactionManager.targetObjects = viewer.scene.children;

添加事件监听

由于 u-space 对象(以及继承自 BaseMeshBaseGroup 的对象)支持自定义事件,你可以像操作 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 键下。

属性

属性类型说明
typeInteractionEventType事件类型字符串(如 'click')。
targetObject3D触发事件的原始 3D 对象(第一个命中点)。
currentTargetObject3D冒泡链中当前处理事件的对象。
intersectIntersection | nullThree.js 射线检测数据:pointfacedistanceuv 等。
originalEventPointerEvent | MouseEvent原始 DOM 指针/鼠标事件。

方法

stopPropagation()

阻止事件继续向上冒泡。

InteractionManager API

属性

属性类型默认值说明
targetObjectsObject3D[]scene.children射线检测的目标对象列表,默认为场景的直接子级。
pointerMoveEventsEnabledbooleanfalse启用 pointermovepointerenterpointerleave 事件。

方法

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);       // 检查是否已选

属性

属性类型说明
selectedSet<Object3D>当前已选对象集合。
selectedArrayObject3D[]当前已选对象数组。
targetObjectsObject3D[]框选时的候选对象(默认为场景子级)。

框选

启用后可用鼠标拖动矩形区域选择多个对象。框选覆盖层会渲染在容器元素上。

typescript
selection.enableBoxSelection({ deep: true });   // 开启框选
selection.disableBoxSelection();                 // 关闭框选

BoxSelectionOptions

属性类型默认值说明
classNamestring框选矩形的 CSS 类名。
deepbooleantrue是否递归检测子对象。

事件

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()

关闭框选、移除事件监听、清空选择集。

u-space docs