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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:05:27