如何让坐标轴随立方体同步运动?(react-three-fiber/Three.js)
解决方案:让坐标轴及标签随立方体同步旋转
一、让坐标轴随立方体同步旋转
当前你的AxesHelper是场景的直接子元素,不会继承立方体的变换。只需将AxesHelper作为立方体mesh的子组件,它就会自动继承父对象的旋转、位移等所有变换。
修改Box组件,把axesHelper放到mesh标签内部:
const Box = (props) => { const ref = useRef() const websocketRef = useRef(); const connectWebsocket = () => { if (!websocketRef.current) { socket.addEventListener("message", (ev) => { if (ev.data.includes('ahrs_yaw')) { setPose(JSON.parse(ev.data.replaceAll("'", '"'))) } }); websocketRef.current = socket; } }; connectWebsocket(); useFrame(() => { ref.current.rotation.x += .005 ref.current.rotation.y += .005 ref.current.rotation.z += .005 }) return ( <mesh {...props} ref={ref} > <boxGeometry args={[3, 3, 3]} /> <meshStandardMaterial color={'orange'} /> {/* 将AxesHelper作为立方体的子元素 */} <axesHelper args={[5]} /> </mesh> ) }
同时删除Canvas中单独的<axesHelper args={[5, 5, 5]} />,此时坐标轴会完全跟随立方体旋转。
二、添加跟随立方体的坐标轴标签
1. 改造为可复用的轴标签组件
创建一个能自动面向相机的文本组件,确保标签始终可读:
import { extend, useFrame, useThree } from '@react-three/fiber' import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js' import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js' import helvetiker from "three/examples/fonts/helvetiker_regular.typeface.json" extend({ TextGeometry }) const helvetikerRegular = new FontLoader().parse(helvetiker) const textOptions = { font: helvetikerRegular, size: .4, depth: .2, } // 可复用的坐标轴标签组件 function AxisLabel({ text, color, position }) { const meshRef = useRef() const { camera } = useThree() // 让文本始终面向相机 useFrame(() => { meshRef.current.lookAt(camera.position) }) return( <mesh ref={meshRef} position={position}> <textGeometry attach='geometry' args={[text, textOptions]}/> <meshStandardMaterial attach='material' color={color}/> </mesh> ) }
2. 在立方体中添加三个轴标签
将标签作为立方体的子元素,位置对应各坐标轴末端(可根据立方体大小调整):
const Box = (props) => { // ... 原有代码不变 ... return ( <mesh {...props} ref={ref} > <boxGeometry args={[3, 3, 3]} /> <meshStandardMaterial color={'orange'} /> <axesHelper args={[5]} /> {/* 添加三个坐标轴标签 */} <AxisLabel text="X" color="red" position={[2, 0, 0]} /> <AxisLabel text="Y" color="green" position={[0, 2, 0]} /> <AxisLabel text="Z" color="blue" position={[0, 0, 2]} /> </mesh> ) }
关键原理
- Three.js中父子对象的变换是继承的:子对象会自动继承父对象的
position、rotation、scale,因此将辅助器和标签绑定到立方体即可同步运动。 lookAt(camera.position)确保文本始终朝向相机,避免旋转后标签倒置无法阅读。
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

