之前已经用Threejs在三维世界里面创建了很多模型,那么有个疑问来了,三维世界中能否拿来写字呢?后来去查了一下发现是可以的,那么今天就来试一下Threejs里面的三维文本--TextGeometry
TextGeometry
首先如果想要创建TextGeometry
的话,不能在Threejs的标准库里面找,得额外的导入进来
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry";
其次,细心的朋友可能已经发现了,TextGeometry
它其实就是ExtrudeGeometry
的子类,这个意味着它也是有一个二维图形拉伸成为三维图形的,ExtrudeGeometry
的属性一样适用于TextGeometry
,不记得的可以先去复习一下,现在我们就来创建三维文本,有过前端开发经验的朋友肯定知道,如果需要显示一个文本,那么必须得有个字体,Threejs里面也是一样,第一步就是去加载字体,这里用到了FontLoader
这个类,使用下面这行代码导入进来
import { FontLoader } from "three/examples/jsm/loaders/FontLoader";
FontLoader
使用load
函数去加载字体
export class FontLoader extends Loader<Font> {
constructor(manager?: LoadingManager);
load(
url: string,
onLoad?: (data: Font) => void,
onProgress?: (event: ProgressEvent) => void,
onError?: (err: unknown) => void,
): void;
parse(json: FontData): Font;
}
其中第一个参数url
就是字体的加载路径,通常都是本地文件路径,Threejs已经提供给了一些字体给我们使用,它们都在node_modules/three/examples/fonts里面
可以看到FontLoader
加载的字体都是一些json文件,不是直接去加载ttf或者otf文件,当然我们不能直接从node_modules里面直接去加载这些json文件,需要把它们拷贝出来到项目的资源目录下才可以
那么load
函数的第一个参数有了,当FontLoader
去加载这个字体的时候,它提供了三个回调函数来获取对应的结果
onLoad
:加载成功,并且回调一个Font对象onProgress
:加载中,并回调一个加载进度对象onError
:加载失败
我们这里只使用onLoad
函数来获取它的加载结果
var fontload = new FontLoader();
fontload.load(`/fonts/gentilis_bold.typeface.json`, (res) => {
});
在回调函数中就可以用加载得到的Font
对象来创建我们的三维文本了,创建文本的函数如下
function loadedFont(data: Font) {
const textGeometry = new TextGeometry("Test My Text", {
font: data,
size: 6,
depth: 5,
bevelEnabled: true,
});
const textMaterial = new THREE.MeshStandardMaterial({
color: 0x9400d3,
metalness: 0.9,
roughness: 0.3,
});
const textMesh = new THREE.Mesh(textGeometry, textMaterial);
return textMesh;
}
虽说TextGeometry
是ExtrudeGeometry
的子类,但是是否启用倒角的默认值却是不一样的,ExtrudeGeometry
是默认启用倒角的,而TextGeometry
是默认不启用倒角,所以这里显式的设置了bevelEnabled
为true
,将loadedFont
函数添加到onLoad
函数中,文本就创建成功了
var fontload = new FontLoader();
fontload.load(`/fonts/gentilis_bold.typeface.json`, (res) => {
scene.add(loadedFont(res));
});
部分文字在屏幕外面,这个没关系因为x轴是从坐标0开始往正方向绘制的,一会我们可以让它滚动起来,倒角有点大这个倒是需要调整下
const textGeometry = new TextGeometry("Test My Text", {
font: data,
size: 6,
depth: 5,
bevelEnabled: true,
bevelThickness:0.5,
bevelSize:0.5
});
将倒角深度与倒角与文本的距离都调整为0.5后,现在的文本就看起来好多了,现在文本都是英文的,我们试试看能不能加载中文,写点大家喜欢的
const textGeometry = new TextGeometry("一夜暴富,hahaha", {
font: data,
size: 6,
depth: 5,
bevelEnabled: true,
bevelThickness:0.5,
bevelSize:0.5
});
发现中文部分加载不出来,变成乱码了,原因是Threejs自带的字体是不支持加载中文的,如果想要加载的话,就必须去添加自定义字体
添加自定义字体
从网上找了一圈,下了个免费的支持中文的ttf字体包,那么问题来了,前面说过FontLoader
无法直接加载ttf字体包,那么如何将ttf转换成json文件呢,这里推荐一个网站facetype.js 这里面可以将ttf文件转换成json文件
第一步选择文件,将下载好的ttf文件导入进来,然后其他选项都使用默认的,点击convert按钮,转换好的json文件就被下载下来了,现在只需要将下载下来的文件导入到项目的资源目录下,就可以去加载它了
var fontload = new FontLoader();
fontload.load(`/fonts/custom_wenyi.json`, (res) => {
scene.add(loadedFont(res));
});
就这样我们成功的将中文也加载了出来,接下来就让文字滚动起来,达到飘的效果
文字滚动
需要实现文字滚动的话就必须改变文字的坐标,所以我们需要一个变量来保存创建好的三维字体
let textMesh = new THREE.Mesh()
var fontload = new FontLoader();
fontload.load(`/fonts/custom_wenyi.json`, (res) => {
textMesh = loadedFont(res)
scene.add(textMesh);
});
然后在循环渲染的函数中不断减去textMesh的横坐标就好了,代码如下
let target = 100
const update = () => {
requestAnimationFrame(update);
if(textMesh){
textMesh.position.x -= 0.5
target -= 0.5
if(target < 0){
target = 100
textMesh.position.x = 0
}
}
render.render(scene, camera);
};
update();
这里的代码可以让文字从右边移动到左边后达到一定的阈值,重新从右边开始移动,另外既然是暴富,那么咱把文字颜色也给染成金色的
const textMaterial = new THREE.MeshStandardMaterial({
color: 0xFFD700,
metalness: 0.9,
roughness: 0.3,
});
现在来看看效果
总结
本篇文章主要学习了如何在三维世界中创建文本几何体,熟悉了TextGeometry的用法,并且知道了如何将ttf文件转换为Threejs需要的json文件,欢迎各位佬们多多指点,拜拜~