使用Three.js+Parcel加载字体报错Unsupported OpenType signature求助
解决Three.js + Parcel环境下TTFLoader加载字体出现“Unsupported OpenType signature”错误
问题描述
我有一个Three.js项目,采用Parcel作为模块打包工具,尝试通过Three.js的TTFLoader加载字体时,出现“Unsupported OpenType signature”错误。查阅相关问题后,排除了字体相对路径的问题,不清楚错误的真正根源。
错误信息
Unsupported OpenType signature
项目结构
项目根目录包含fonts文件夹(存放Mont-Regular.ttf字体文件)、核心业务文件app.js等。
报错代码片段(app.js)
// load font -- three font const ttfLoader = new TTFLoader(); ttfLoader.load('fonts/Mont-Regular.ttf', (json) => { const font = new FontLoader(json); this.textGeo = new TextGeometry('Hello Text', { font: font, size: 200, height: 50, curveSegments: 12, }); this.textMaterial = new THREE.MeshPhongMaterial({ color: 0xff0000, side: THREE.DoubleSide, }); this.textMesh = new THREE.Mesh(this.textGeo, this.textMaterial); this.textMesh.position.set(0, 0, 0); }); this.scene.add(this.textMesh);
问题根源与解决方法
1. FontLoader使用方式错误
TTFLoader加载完成后返回的是解析后的字体JSON对象,FontLoader本身是用于加载JSON格式字体文件的加载器,不能直接传入JSON对象实例化。正确做法是用Font类包装TTFLoader返回的JSON:
import { Font } from 'three/addons/loaders/FontLoader.js'; ttfLoader.load('fonts/Mont-Regular.ttf', (fontJson) => { const font = new Font(fontJson); // 使用Font类包装,而非FontLoader // 后续创建TextGeometry逻辑 });
2. Parcel资源处理异常
Parcel可能对TTF字体文件进行错误转码,导致TTFLoader无法解析原始二进制数据。可以通过以下方式修复:
- 在项目根目录创建
.parcelrc文件,添加规则禁止Parcel转码TTF文件:
{ "transformers": { "*.ttf": ["@parcel/transformer-raw"] } }
- 或者通过ES模块导入方式获取字体的正确URL,避免路径解析问题:
import fontUrl from './fonts/Mont-Regular.ttf'; ttfLoader.load(fontUrl, (fontJson) => { // 后续逻辑 });
3. 异步加载导致的场景添加错误
ttfLoader.load是异步操作,你在加载完成前就执行了this.scene.add(this.textMesh),此时this.textMesh尚未初始化,会引发额外错误。需要将场景添加代码移到回调函数内部:
ttfLoader.load(fontUrl, (fontJson) => { const font = new Font(fontJson); this.textGeo = new TextGeometry('Hello Text', { font: font, size: 200, height: 50, curveSegments: 12, }); this.textMaterial = new THREE.MeshPhongMaterial({ color: 0xff0000, side: THREE.DoubleSide, }); this.textMesh = new THREE.Mesh(this.textGeo, this.textMaterial); this.textMesh.position.set(0, 0, 0); this.scene.add(this.textMesh); // 移到回调内确保实例化完成 });
内容的提问来源于stack exchange,提问作者Reynald Lamury
相关产品推荐
相关产品推荐

