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

React Three Fiber使用TextGeometry报迁移错误且刷新后失效问题

问题产生原因

报错和刷新后文字消失的问题由三个核心问题共同导致:

  1. Three.js 官方将TextGeometry移动到examples目录后,类内部自带路径校验逻辑,会主动检查全局THREE对象下是否存在TextGeometry属性,不存在就抛出指定路径迁移的报错。仅通过@react-three/fiber的extend方法注册自定义元素,不会修改全局THREE对象,因此会触发校验报错。
  2. 字体解析逻辑写在组件模块顶层,React 18+默认开启的严格模式会重复执行模块副作用,导致font实例重复生成、TextGeometry重复注册,刷新页面时出现引用冲突,geometry生成失败。
  3. 代码中未给承载文字的<mesh>添加材质,同时环境光强度设置过低(仅0.1),首次加载时因资源缓存可能碰巧显示,刷新后重新走渲染流程时,无材质的网格不会被WebGL绘制,加上光照不足,文字视觉上完全消失。
修复步骤
  • 引入TextGeometry后,手动将其挂载到全局THREE对象上,绕过内部路径校验
  • 将字体加载、参数配置逻辑移入组件内部,用R3F提供的useLoader加载字体资源,用useMemo缓存geometry配置,避免重复实例化引发的引用冲突
  • 为文字网格添加标准材质,调整光照参数到合理范围,保证文字可见
  • 给<textGeometry>添加绑定文本内容的key,文本变化时正确重建几何体
修复后完整代码

TextMesh 组件

import { extend, Object3DNode, useLoader } from '@react-three/fiber';
import * as React from 'react';
import * as THREE from 'three';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';
// 手动挂载到THREE全局,解决内部路径校验报错
THREE.TextGeometry = TextGeometry;
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
import monster from '../assets/fonts/Montserrat_Bold.json';

// 仅执行一次元素注册
extend({ TextGeometry });

declare global {
  namespace JSX {
    interface IntrinsicElements {
      textGeometry: Object3DNode<TextGeometry, typeof TextGeometry>;
    }
  }
}

export interface ITextMeshProps {
  text?: string;
  size?: number;
  height?: number;
  color?: string;
}

export function TextMesh(props: ITextMeshProps) {
  const { text = 'Test', size = 2, height = 1, color = '#ffffff' } = props;
  // 用R3F官方loader钩子加载字体,自动处理缓存和销毁
  const font = useLoader(FontLoader, monster);
  // 缓存几何体配置,避免重渲染重复生成几何体
  const geometryOptions = React.useMemo(() => ({
    font,
    size,
    height,
    curveSegments: 12,
    bevelEnabled: true,
    bevelThickness: 0.03,
    bevelSize: 0.02,
    bevelOffset: 0,
    bevelSegments: 5
  }), [font, size, height]);

  return (
    <mesh>
      <textGeometry key={text} args={[text, geometryOptions]} />
      {/* 必须添加材质才能正常渲染 */}
      <meshStandardMaterial color={color} />
    </mesh>
  );
}

App 入口组件

import React from 'react';
import { Canvas } from '@react-three/fiber'
import { TextMesh } from './TextMesh';

function App() {
  return (
    <div className='h-screen flex items-center justify-center flex-col bg-orange-300'>
      <Canvas camera={{ position: [0, 0, 10], fov: 50 }}>
        {/* 调整光照强度到合理范围,避免文字过暗不可见 */}
        <ambientLight intensity={0.6} color="white" />
        <spotLight color="white" position={[20, 10, 10]} angle={0.3} penumbra={1} intensity={1}/>
        <TextMesh text="Test" color="#2563eb" />
      </Canvas>
    </div>
  );
}

export default App;
额外注意事项
  • 确认依赖版本匹配:three版本≥0.148.0,@react-three/fiber版本≥8.12.0,避免版本不兼容引发的注册异常
  • 不要在模块顶层直接执行new FontLoader().parse()解析字体,该操作会生成全局副作用,严格模式下极易出现引用失效问题
  • 如果不需要自定义字体生成逻辑,也可以直接使用@react-three/drei提供的<Text>组件,已经封装好了TextGeometry的所有兼容处理,无需手动注册类和加载字体。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:06:22