React-three-fiber中3D模型自定义文本超出边界适配问题求助
解决React-three-fiber中@react-three/drei Text组件超出3D模型边界的问题
我对Three.js不熟悉,开发时采用React-three-fiber框架(将Three.js功能封装为组件)。需求是给3D模型添加用户自定义文本功能,但使用@react-three/drei的Text组件时,文本超出了模型边界,期望文本能适配模型区域(可向上调整位置以贴合模型)。已尝试将Text组件放在模型原有文本材质的相同位置,但问题仍存在。
Three_d_model组件代码
import { Canvas, useThree, useFrame } from '@react-three/fiber' import { Suspense } from 'react' import { OrbitControls, useGLTF, Text, useTexture, useHelper } from '@react-three/drei' const Three_d_model = ({ name, setBackGroundColor, backLogo, frontLogo, backgroundColor, qrBlock }) => { const ref = useRef('') const configurator = useSelector(state => state.configurator) const dispatch = useDispatch(); const downloadImage = () => { const my_canvas = ref.current console.log("my_canvas", my_canvas) var link = document.createElement('a'); link.download = 'filename.png'; link.href = my_canvas.toDataURL() link.click(); } return ( <> <div className="w-screen h-screen rounded-xl"> <Canvas shadowMap camera={{ fov: 75, near: 0.1, far: 1000, position: [0, 0, -2] }} ref={ref} gl={{ preserveDrawingBuffer: true }} > <ambientLight intensity={2} /> <spotLight intensity={0.5} angle={0.1} penumbra={1} position={[10, 15, 10]} castShadow /> <Suspense fallback="Loading..."> <OrbitControls enablePan={true} enableRotate={true} enableZoom={true} /> <Model configurator={configurator} /> </Suspense> </Canvas> </div> </> ) }
Model组件代码
function Model({ configurator, ...props }) { const group = useRef() const { nodes, materials } = useGLTF('/3dCard10.gltf') return ( <group {...props} dispose={null}> <mesh geometry={nodes.card.geometry} material={materials['card color']} material-color={`${configurator.backgroundColor}`} /> <mesh geometry={nodes['qr-code-outline'].geometry} material={materials['qr code outline']} material-color={`${configurator.qrBlockColor}`} /> <mesh geometry={nodes.nfc.geometry} material={materials['qr code outline']} material-color={`${configurator.qrBlockColor}`} /> {/* <mesh geometry={nodes.Text.geometry} material={materials.text} position={[-0.87, 0.11, 0.01]} rotation={[1.57, 0, 0]} /> */} <mesh geometry={nodes['qr-code'].geometry} material={materials.qrcode} /> <mesh geometry={nodes['horizontal-logo'].geometry} material={materials['horizontal-logo']} position={[-0.52, 0.96, 0.01]} rotation={[0, 0, 0]} scale={[1,1,1]} /> <mesh geometry={nodes.Cube.geometry} material={materials['logo-vertical']} position={[0, 0.2, -0.01]} rotation={[0, 0, 0]} scale={[1,1,1]} /> <Text position={[-0.45, 0.11, 0.01]} lineWidth="12px" scale={1} color={get_text_color(configurator.backgroundColor)} backgroundColor="#FFC642" width={'1px'} textAlign='left' maxWidth={'13px'} minWidth={'12px'} > {configurator.text} </Text> </group> ) }
解决方案
1. 修正Text组件的单位与基础参数
@react-three/drei的Text组件用的是Three.js的3D空间单位,不是CSS的px,你设置的maxWidth={'13px'}、width={'1px'}完全不符合预期。改成数值类型的3D单位,同时调整位置和缩放:
<Text position={[-0.45, 0.3, 0.01]} // 向上调整y轴位置,贴合模型上部区域 scale={0.8} // 根据模型文本区域大小缩小比例 color={get_text_color(configurator.backgroundColor)} backgroundColor="#FFC642" width={2} // 3D空间单位,对应文本可占用的宽度 textAlign='left' maxWidth={2} // 超过这个宽度自动换行 fontSize={0.2} // 控制文本字号,适配模型 > {configurator.text} </Text>
2. 利用原有模型文本的边界自动适配
如果模型里原有nodes.Text节点(你代码里注释掉了),可以用它的边界框来精准定位新Text组件,保证完全贴合模型区域:
import { useBoundingBox } from '@react-three/drei' import * as THREE from 'three' function Model({ configurator, ...props }) { const group = useRef() const { nodes, materials } = useGLTF('/3dCard10.gltf') // 获取原有文本几何体的边界框 const { boundingBox } = useBoundingBox(nodes.Text) return ( <group {...props} dispose={null}> {/* 其他mesh组件保持不变 */} <Text // 对齐原有文本的左上角边界 position={[boundingBox.min.x, boundingBox.max.y, 0.02]} // 根据原有文本的宽度自动计算缩放比例 scale={boundingBox.getSize(new THREE.Vector3()).x / 8} color={get_text_color(configurator.backgroundColor)} backgroundColor="#FFC642" // 匹配原有文本的宽度,防止溢出 maxWidth={boundingBox.getSize(new THREE.Vector3()).x} textAlign='left' fontSize={0.15} > {configurator.text} </Text> </group> ) }
注意要先取消原有nodes.Text的注释,确保这个节点能被正确获取。
3. 移除无效属性
@react-three/drei的Text组件不支持lineWidth、minWidth这类CSS属性,直接删掉这些无效配置,避免干扰组件渲染。
内容的提问来源于stack exchange,提问作者MUHAMMAD ZAIN
相关产品推荐
相关产品推荐

