如视 Five SDK
    Preparing search index...

    Gesture (手势与事件)

    • Summary: Five 提供了一套跨平台的手势事件系统,抹平了 PC 与移动端的差异,并针对不同 Mode 提供了默认的交互逻辑。
    • Schema: GestureEvent 继承自 StateEvent,包含了手势中心点、射线等信息。
    • Concepts: Gesture Type, Default Behavior, PreventDefault。
    • Examples: 阻止默认行为、点击添加标记。

    Definition: GestureEvent

    所有手势事件的回调参数均为 GestureEvent 类型:

    import { State } from "@realsee/five";
    import * as THREE from "three";

    interface GestureEvent {
    type: string; // 事件类型,如 "gesture.tap"
    timeStamp: number; // 时间戳
    target: EventTarget | null;
    pointerType: 'touch' | 'pen' | 'mouse' | 'kinect';

    // 手势中心点信息
    center: {
    x: number; // 屏幕 X 坐标
    y: number; // 屏幕 Y 坐标
    raycaster: THREE.Raycaster; // 从相机发出的射线(已包含坐标变换)
    };

    // 当前相机状态
    state: State;

    // 是否是用户触发(区别于代码调用)
    userAction: boolean;

    // 阻止默认行为
    preventDefault(): void;
    defaultPrevented: boolean;
    }

    Five 的手势系统基于 Hammer.js 封装,主要包含以下几种手势:

    • gesture.fire: 任意事件被触发。
    • gesture.pan: 拖拽/平移。
    • gesture.pinch: 双指缩放。
    • gesture.tap: 点击。
    • gesture.dbltap: 双击。
    • gesture.press: 长按。
    • gesture.mousewheel: 鼠标滚轮。

    不同的 Mode 对手势有不同的默认响应

    手势 Panorama (全景) Mapview (模型) 说明
    Pan 旋转相机视角 (Look around) 围绕模型旋转/平移相机 (Orbit/Pan)
    Pinch 调整 FOV (Zoom in/out) 调整相机距离 (Distance)
    Tap 移动点位 (Move to pano) 切换到全景 (Enter pano) 若点击到地面/模型,Mapview 下默认无响应,除非点击到点位标记
    DblTap 动画调整 FOV 聚焦并拉近视角 (Fly to)
    MouseWheel 调整 FOV 调整相机距离

    Five 的事件触发顺序如下:

    1. Emit Event: Five 触发 gesture.xxx 事件。
    2. User Callback: 开发者注册的监听函数被执行。
    3. Default Behavior: 如果开发者没有调用 event.preventDefault(),Five 执行默认逻辑(如旋转相机、移动点位)。

    因此,如果你想自定义交互(例如:点击不走点,而是弹出一个框),必须调用 event.preventDefault()

    监听点击事件并打印日志:

    five.on("gesture.tap", (event) => {
    console.log("点击位置:", event.center.x, event.center.y);
    // event.center.raycaster 可以用来做射线检测
    });

    这个示例展示了如何通过点击事件在场景中添加一个红色的球体,并阻止 Five 默认的点位移动行为。

    import * as THREE from "three";
    import { Five } from "@realsee/five";

    const five = new Five();

    five.on("gesture.tap", (event) => {
    // 1. 阻止默认行为(防止点击地面时 Five 自动走点或切换模式)
    event.preventDefault();

    // 2. 获取射线
    const raycaster = event.center.raycaster;

    // 3. 检测与模型的碰撞
    // five.model.intersectRaycaster 是 Five 提供的便捷方法,会自动检测所有可见模型
    const intersects = five.model.intersectRaycaster(raycaster);

    if (intersects.length > 0) {
    const intersect = intersects[0];
    const point = intersect.point; // 碰撞点世界坐标

    console.log("点击到了模型,坐标:", point);

    // 4. 创建一个小球
    const geometry = new THREE.SphereGeometry(0.1, 32, 32);
    const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
    const sphere = new THREE.Mesh(geometry, material);

    // 5. 设置位置并添加到场景
    sphere.position.copy(point);
    five.scene.add(sphere);

    // 强制刷新渲染,确保小球立即出现
    five.needsRender = true;
    } else {
    console.log("未点击到任何模型");
    }
    });
    five.on("gesture.pinch", (event) => {
    // 获取当前 FOV
    const currentFov = five.state.fov;

    // 假设我们限制 FOV 在 80 到 100 之间
    // 注意:这只是逻辑演示,Five 内部有自己的 minFov/maxFov 配置,
    // 这里演示如何完全接管控制权。
    if (currentFov < 80 || currentFov > 100) {
    // 阻止 Five 的默认缩放
    event.preventDefault();
    console.log("已达到缩放极限");
    }
    });
    • 查看事件触发: 在控制台监听所有手势。
      ["pan", "tap", "pinch", "press"].forEach(type => {
      five.on(`gesture.${type}` as any, (e) => console.log(type, e));
      });
    • Helper Line: 如果射线检测不准,可以画出射线辅助线。
      five.scene.add(new THREE.ArrowHelper(raycaster.ray.direction, raycaster.ray.origin, 10, 0xff0000));
      five.needsRender = true;
    1. 忘记 preventDefault: 如果你发现点击后既生成了小球,相机又自动飞走了,通常是因为没有调用 event.preventDefault()
    2. 坐标系混淆: event.center.x/y 是屏幕像素坐标,event.center.raycaster 已经处理了屏幕到世界的转换。直接使用 raycaster 最安全。
    3. 点击穿透: 如果场景中有 HTML 覆盖层(如按钮),HTML 元素的点击事件可能会冒泡或被 Five 捕获。建议在 HTML 元素上使用 stopPropagation 或判断 event.target

    tags: [手势, 点击, 拖拽, 缩放, 长按, 鼠标, 触摸, 交互控制, 自定义交互, gesture, event, interaction, tap, pan, pinch, preventDefault]