You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Drei PivotControls拖动后,如何获取Mesh的更新位置?

解决Drei PivotControls拖动后获取Mesh位置的问题

问题原因

你遇到位置始终显示[0,0,0]的核心原因有两个:

  1. 你的<primitive>组件通过position={position}绑定了受控状态值,React Three Fiber会在每次渲染时将Mesh位置重置为该状态值,覆盖PivotControls的修改;
  2. 你直接访问的是<primitive>组件引用,而Mesh的实际位置存储在其内部的3D对象上,而非组件本身。

修复方案

1. 移除受控position绑定(非必要场景)

如果不需要通过state控制Mesh位置,先去掉<primitive>上的position={position},让PivotControls直接操控Mesh的transform:

const meshRef = useRef();
const handleDragEnd = () => {
    const model = meshRef.current;
    // 获取本地位置(相对于父对象的坐标)
    const localPos = model.object.position;
    console.log('本地位置:', `${localPos.x}, ${localPos.y}, ${localPos.z}`);
    
    // 若需要世界位置,先更新矩阵再获取
    const worldPos = new THREE.Vector3();
    model.object.getWorldPosition(worldPos);
    console.log('世界位置:', `${worldPos.x}, ${worldPos.y}, ${worldPos.z}`);
};

return (
    <PivotControls anchor={[0, 0, 0]} onDragEnd={handleDragEnd}>
        <primitive ref={meshRef} scale={scale} rotation={rotation} object={loadedModel.scene} />
    </PivotControls>
)

2. 同步受控state(需state管理位置场景)

如果必须用state管理位置,需要在onDragEnd事件中同步更新state,避免渲染时的位置重置:

const [position, setPosition] = useState([0, 0, 0]);
const meshRef = useRef();

const handleDragEnd = () => {
    const obj = meshRef.current.object;
    // 将PivotControls修改的位置同步到state
    setPosition([obj.position.x, obj.position.y, obj.position.z]);
    console.log('更新后的位置:', obj.position);
};

return (
    <PivotControls anchor={[0, 0, 0]} onDragEnd={handleDragEnd}>
        <primitive ref={meshRef} scale={scale} position={position} rotation={rotation} object={loadedModel.scene} />
    </PivotControls>
)

关键说明

  • <primitive>的ref指向组件实例,内部的3D对象需通过.object属性访问;
  • 调用getWorldPosition()获取世界位置前,确保对象的矩阵已更新(默认拖动后会自动更新);
  • 使用受控state时,必须同步PivotControls的修改到state,否则R3F的渲染逻辑会重置Mesh位置。

内容的提问来源于stack exchange,提问作者Ashbury

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 00:23:23