mcpField
R
r3f-interaction

r3f-interaction

github.com/enzed开发1313.3k 次安装8 周前更新
代码仓库

关于 r3f-interaction

面向 React Three Fiber 开发者的交互技能,提供指针、拖拽、相机和键盘输入的实现指导。重点说明事件语义、输入所有权与边界情况的验证。

主要功能

  1. 01R3F 指针事件语义
  2. 02对象拖拽与控制器协调
  3. 03键盘和连续输入处理
  4. 04触屏、捕获与取消处理
  5. 05交互边界情况测试

适用场景

  1. 01实现可选择的 3D 对象
  2. 02避免拖拽与相机控制冲突
  3. 03处理触屏及画布外拖动
  4. 04验证键盘输入和焦点行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/enzed/r3f-skills --skill r3f-interaction

安装后在 Claude Code 中输入/r3f-interaction确认已加载。

详细介绍

React Three Fiber 交互

先检查已安装的 Fiber、Drei 和输入库版本。示例针对 Fiber 9 / React 19。连接处理程序之前,先确定由谁负责相机移动、对象移动和 UI 输入。

可选对象

在 Canvas 下挂载。重要操作应在 Canvas 外保留可访问的 DOM 控件;仅靠网格指针处理程序无法提供键盘访问。

import { useState } from 'react'
import { OrbitControls } from '@react-three/drei'

export default function Example() {
  const [selected, setSelected] = useState(false)
  return (
    <>
      <mesh
        name="selectable-box"
        onClick={(event) => {
          event.stopPropagation()
          setSelected((value) => !value)
        }}
      >
        <boxGeometry />
        <meshStandardMaterial color={selected ? 'gold' : 'coral'} />
      </mesh>
      <OrbitControls makeDefault />
    </>
  )
}

事件语义

  • R3F 会对带有处理程序的对象进行射线检测,并按距离顺序分发命中事件,然后沿祖先链冒泡。event.object 是命中的对象;event.eventObject 是拥有处理程序的对象。
  • stopPropagation() 会阻止事件分发到更远处的命中对象以及祖先对象。它会改变事件分发,不会跳过已经执行的射线检测。调用它可能会立即在此前位于命中对象后方的悬停对象上触发 pointerout。
  • event.point 使用世界坐标。保留值时请先克隆,并在赋给局部变换之前转换到父级的局部空间。要将 2D 拖动映射到 3D,需要平面交点或深度参考。
  • 使用 Canvas 的 onPointerMissed 处理背景取消选择;根据事件的移动信息和应用的手势策略区分点击与拖动。
  • 在 R3F 中,指针捕获是对命中测试的补充。通过 event.target.setPointerCapture(event.pointerId) 和对应的释放方法进行捕获和释放;还要处理取消和捕获丢失的情况。
  • 指针静止时相机移动,可能需要调用 state.events.update() 刷新悬停结果。仅在必要时调用,不要每帧都额外进行一次射线检测。
  • 对于开销较大的拾取操作,请使用更简单的命中代理或图层过滤。不要仅依靠视觉透明度来阻止相交。

控件与拖动的责任归属

  • 使用 OrbitControls 进行环绕;需要脚本化过渡和更丰富的相机行为时,使用 CameraControls。复制属性或方法之前,请检查已安装的 Drei / 底层控件版本。
  • Drei 控件会管理帧更新和按需失效。在同一相机上挂载多个活动控件时,除非已明确协调,否则应避免这样做。
  • makeDefault 会向与控件协调的辅助工具提供控件实例。拖动时,TransformControls 可以暂停默认控件;请确认自定义控件也能正确禁用和恢复。
  • 对象拖动时,应根据所需约束选择 Drei DragControls/PivotControls/TransformControls。区分受控矩阵与自动变换;不要同时对同一对象应用两者。
  • 自定义拖动时,保存初始变换、捕获指针、投影到选定平面,并在 pointerup、取消和卸载时恢复相机控件。请在实际事件目标上遵循 touch-action 要求。
  • 共享的 DOM 事件源需要与事件目标和画布矩形一致的坐标前缀。请测试滚动和叠加层;盲目选择 client 坐标可能造成偏移。

键盘与连续输入

  • Drei KeyboardControls 提供命名操作。移动时,在 useFrame 内读取其 getter;仅在离散事件中订阅,并清理订阅。
  • 如果需要保持恒定速度,请对对角移动进行归一化;视觉移动需乘以 delta。对于物理刚体,应将输入传递给物理步进逻辑,而不是直接移动其网格。
  • 焦点丢失时清除按住状态,并注意文本字段的焦点。指针锁定、全屏和音频可能需要明确的用户手势。
  • 高频指针位置使用 refs,语义事件使用 React state。不要仅为节流一个处理程序而添加 lodash 或状态库;确有节流需要时,请清理计时器。
  • ScrollControls 会创建滚动上下文;useScroll 应放在其下方。其归一化的 offset/delta 不是像素距离。

验证

测试重叠网格、嵌套组、点击背景取消选择、拖动到画布外、触控、取消操作、焦点丢失以及键盘替代操作。验证拖动后相机控件能否恢复正常。

来源

评论

支持 Markdown