前言
本篇是学习three.js官网上geometry_text_shapes、geometry_text_stroke 和 geometry_text 示例,了解如何在3D 空间内展示文本内容。
实现
添加基本代码结构
import * as THREE from 'three';
let camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, - 400, 600 );
let scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const consorl = new OrbitControls(camera, renderer.domElement);
consorl.target.set(0,0,0);
consorl.update();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene,camera);
}
animate();
WebGLRenderer 参数 antialias 为抗锯齿,默认为false,当开启时可以柔滑物体外形,提升画面质量。
OrbitControls(轨道控制器)的 target 属性是指控制器的焦点,即轨道会围绕着这个点而运动。
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js';
const loader = new FontLoader();
loader.load('font/helvetiker_regular.typeface.json', function (font) {
......
});
FontLoader 用于加载JSON格式的字体。
.load ( url : String, onLoad : Function, onProgress : Function, onError : Function ) : undefined
属性 | 描述 |
---|---|
url | 文件的URL或者路径 |
onLoad | 将在加载完成时调用。参数是将要被加载的font。 |
onProgress | 将在加载过程中调用。 |
onError | 将在加载错误时调用。 |
加载完成返回的字体为 Font 类型。其中 generateShapes 方法可以将文本加载为shape数组。
generateShapes(text: string, size: number): Shape[];
属性 | 描述 |
---|---|
text | 要加载的文本 |
size | 文本大小 |
在loader.load 的onLoad 回调中继续添加代码:
const color = new THREE.Color(0x006699);
const matLite = new THREE.MeshBasicMaterial({
color: color,
transparent: true,
opacity: 0.4,
side: THREE.DoubleSide,
});
const message = ' Three.js\nSimple text.';
const shapes = font.generateShapes(message, 100);
const geometry = new THREE.ShapeGeometry(shapes);
geometry.computeBoundingBox();
const xMid = - 0.5 * (geometry.boundingBox.max.x - geometry.boundingBox.min.x);
geometry.translate(xMid, 0, 0);
const text = new THREE.Mesh(geometry, matLite);
text.position.z = -150;
scene.add(text);
MeshBasicMaterial 是基础网格材质,不受光照影响。
color | 材质颜色 |
transparent | 材质是否透明 |
opacity | 在0.0 - 1.0的范围内的浮点数,表明材质的透明度。值0.0表示完全透明,1.0表示完全不透明。 |
side | 定义渲染那一面,默认只渲染正面(THREE.FrontSide),其他选项有背面(THREE.BackSide),双面(THREE.DoubleSide)。 |
将要渲染的文本通过 font.generateShapes
方法得到shape(二维形状平面)数组。再生成ShapeGeometry(形状缓冲几何体)。
computeBoundingBox() 方法是计算出 geometry 的 boundingBox(外边界矩形),通过计算和 translate 方法将 geometry 的中心移动到原点上。
生成mesh 添加到场景中。
添加线性文字
const matDark = new THREE.LineBasicMaterial({
color: color,
side: THREE.DoubleSide
});
const linePoints: THREE.Vector2[][] = [];
for (let i = 0;i < shapes.length;i++) {
const shape = shapes[i];
linePoints.push(shape.getPoints());
if (shape.holes && shape.holes.length > 0 && i !== 4) {
for (let j = 0 ; j < shape.holes.length;j++) {
const hole = shape.holes[j];
linePoints.push(hole.getPoints());
}
}
}
const lineText = new THREE.Object3D();
for (let i = 0 ; i < linePoints.length;i++) {
const points = linePoints[i];
const geometry = new THREE.BufferGeometry().setFromPoints(points);
geometry.translate(xMid, 0,0);
const lineMesh = new THREE.Line(geometry, matDark);
lineText.add(lineMesh);
}
scene.add(lineText);
LineBasicMaterial 是一种线框样式材质。
对 shapes 数组进行遍历,对shape 通过 getPoints 获取组成图形点的序列。有些文字字母上会有 holes 的存在,也同样获取 getPoints 。holes 是图形上的洞,当我们想要用线来描述一个图形时,这些洞就需要单独处理,类似于下图:
Object3D(三维物体)是three.js 中大部分物体的基类,提供了许多三维空间内的物体操控方法,此处是用于文字生成的各个 geometry 的父对象。
将linePoints 遍历 通过setFromPoints() 生成 geometry 添加到 Object3D 父对象,最后把父对象添加到场景中。
添加svg文字
const style = SVGLoader.getStrokeStyle( 5, color.getStyle() );
const strokeText = new THREE.Group();
for (let i = 0 ; i < linePoints.length; i++) {
const points = linePoints[i];
const geometry = SVGLoader.pointsToStroke( points, style );
geometry.translate( xMid, 0, 0 );
const strokeMesh = new THREE.Mesh( geometry, matDark );
strokeText.add( strokeMesh );
}
strokeText.position.z = 150;
scene.add(strokeText);
SVGLoader 用来加载SVG 二维矢量图形的加载器。
添加文字几何体
let textGeo = new TextGeometry(message, {
font: font,
size: 100,
height: 20,
curveSegments: 4,
bevelThickness: 2,
bevelSize: 1.5,
bevelEnabled: true
});
let textMesh1 = new THREE.Mesh( textGeo, matLite );
textMesh1.position.x = xMid;
textMesh1.position.y = 0;
textMesh1.position.z = 300;
scene.add(textMesh1);
TextGeometry 是将文本生成几何体。
属性 | 描述 |
---|---|
font | 字体,HREE.Font的实例。 |
size | 字体大小,默认值为100。 |
height | 挤出文本的厚度。默认值为50。 |
curveSegments | 文本曲线上点的数量。默认值为12。 |
bevelThickness | 文本上斜角的深度,默认值为20。 |
bevelSize | 斜角与原始文本轮廓之间的延伸距离。默认值为8。 |
bevelEnabled | 是否开启斜角,默认为false。 |
bevelSegments | 斜角的分段数。默认值为3。 |
中文文字
在three.js 中展示中文需要引入其他字体文件,上面字体是three.js 官方示例中提供的字体文件,对中文无法识别展示。
windows 电脑 C:\Windows\Fonts
目录之下是计算机安装的字体文件,选择想要的字体文件(.ttf)转为 .json 格式。
转换工具:gero3.github.io/facetype.js…
将转换后的json文件替换上面Font引入代码,再将展示文本换成中文就不会出现乱码了。
结语
本篇是实现3D场景中文字的实现,参考three.js官网示例:
本篇以上代码也已放到了github上:github.com/wenxuan12/3… ,可供做印证参考。