Threejs进阶之十一:使用FontLoader和TextGeometry创建三维文字

Threejs进阶之十一:使用FontLoader和TextGeometry创建三维文字,第1张

在Threejs中我们可以通过FontLoader和TextGeometry结合使用来创建三维文字,FontLoader用于加载JSON格式的字体,FontLoader返回值是表示字体的Shape类型的数组;TextGeometry用于将文本生成为单一的几何体。下面我们先来了解下这两个类

FontLoader

用于加载JSON格式的字体的类。返回font, 返回值是表示字体的Shape类型的数组。 其内部使用FileLoader来加载文件。

构造函数

FontLoader( manager : LoadingManager )
manager — 加载器所使用的loadingManager。默认值为THREE.DefaultLoadingManager.

常用方法

FileLoader常用的方法是.load()方法

.load ( url : String, onLoad : Function, onProgress : Function, onError : Function )
url — 文件的URL或者路径
onLoad — 在加载完成时调用。参数是将要被加载的font
onProgress — 在加载过程中调用。参数是包含total和loaded字节的XMLHttpRequest实例。如果server没有设置header的Content-Length,则total值为0
onError — 在加载错误时调用

注意

这里需要注意的是,FontLoader加载的是JSON格式的字体,Threejs默认提供了一些json格式的字体在/examples/fonts中,可以将其拷贝到项目中直接使用。如果里面没有需要的之前,如中文字体,可以通过facetype.js进行字体转换.

TextGeometry 文本缓冲几何体

TextGeometry 用于将文本生成为单一的几何体的类。 它是由一串给定的文本,以及由加载的font和该几何体ExtrudeGeometry父类中的设置所组成的参数来构造的

构造函数

TextGeometry(text : String, parameters : Object)
text — 将要显示的文本。
parameters — 包含有下列参数的对象:

font — THREE.Font的实例。
size — Float类型。字体大小,默认值为100。
height — Float类型。挤出文本的厚度。默认值为50。
curveSegments — Integer类型。(表示文本的)曲线上点的数量。默认值为12。
bevelEnabled — Boolean类型。是否开启斜角,默认为false。
bevelThickness — Float类型。文本上斜角的深度,默认值为20。
bevelSize — Float类型。斜角与原始文本轮廓之间的延伸距离。默认值为8。
bevelSegments — Integer类型。斜角的分段数。默认值为3。

facetype.js在线转换字体

facetype.js在线转换可以将我们想要转换的ttf格式的字体文件转换为json格式的字体文件,其用法非常简单,打开网站,在选择文件中选择需要转换的ttf文件,默认选中Generate a JSON file (.json),不需要修改,点击下面的Convert即可将ttf转换为json格式,并下载到本地
Threejs进阶之十一:使用FontLoader和TextGeometry创建三维文字,在这里插入图片描述,第2张
这里需要注意,facetype.js只能转换ttf格式的字体

创建三维文字

对FontLoader和TextGeometry有了了解后,我们就可以在场景中创建三维文字了,在我们的vue项目中的components文件夹下新建FontView.vue文件,引入threejs并初始化,这些都是创建Threejs的基本套路,这里就不在赘述了,对Threejs创建的过程还不了解的小伙伴可以看我前面的博客文章。

初始化代码

<template> <div id="scene"></div> </template> <script setup> import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' import { onMounted } from 'vue' let scene,camera,renderer,controls onMounted(()=>{ init() }) function init() { initScene() initCamera() initAxesHelper() initLight() initRenderer() initControls() animate() window.addEventListener('resize',onWindowResize.bind(this)) } // 初始化场景 function initScene() { scene = new THREE.Scene() scene.background = new THREE.Color(0x808080) } // 初始化相机 function initCamera() { camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000) camera.position.set(0,2,2) } // 辅助轴 function initAxesHelper() { const axesHelper = new THREE.AxesHelper(1) scene.add(axesHelper) } // 灯光 function initLight() { const hesLight = new THREE.HemisphereLight(0xffffff,0x444444) hesLight.intensity = 0.6 scene.add(hesLight) const dirLight = new THREE.DirectionalLight() dirLight.position.set(5,5,5) scene.add(dirLight) } // 初始化渲染器 function initRenderer() { renderer = new THREE.WebGLRenderer({antialias:true}) //抗锯齿 // 设置屏幕像素比 renderer.setPixelRatio(window.devicePixelRatio) // 设置大小 renderer.setSize(window.innerWidth,window.innerHeight) // 添加到容器 document.querySelector('#scene').appendChild(renderer.domElement) // 加载阴影 renderer.shadowMap.enable = true } // 初始化轨道控制器 function initControls() { controls = new OrbitControls(camera,renderer.domElement) controls.minPolarAngle = 0 //默认0 // 左键拖动时视窗垂直方向的最大旋转角度。Math.PI/2 为地平线视角 controls.maxPolarAngle = 80 / 360 * 2 * Math.PI // 默认Math.PI,即可以向下旋转到撒旦视角。 controls.update() } function animate() { const delta = clock.getDelta() renderer.render(scene,camera) controls.update(delta) // 当controls.enableDamping=true或者controls.autoRotate=true时调用 requestAnimationFrame(animate) } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth,window.innerHeight) } </script> <style scoped> </style>

创建三维文字

引用FontLoader和TextGeometry

FontLoader位于

three/examples/jsm/loaders/

目录下,
TextGeometry位于

three/examples/jsm/geometries/

目录下

import { FontLoader } from 'three/examples/jsm/loaders/FontLoader' import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry'

创建initFont()方法

创建initFont()方法,在该方法中创建三维文字

创建材质

一个三维文字有两个面组成,分别是文字的正面和拉伸出来的面组成,如果只设置一种材质,则不会有三维立体效果,仍然是二维的文字,可以调整两个材质的颜色不同来观察区别
Threejs进阶之十一:使用FontLoader和TextGeometry创建三维文字,在这里插入图片描述,第3张

const materials = [ new THREE.MeshPhongMaterial({ color:0xffffff, flatShading:true }),//front new THREE.MeshPhongMaterial({color:0xff0000})//back ]

实例化FontLoader对象

const loader = new FontLoader()

调用FontLoader的.load方法,在.load方法中设置要调用的字体和加载成功时的回调

在成功的回调中主要处理以下几个逻辑
1、创建TextGeometry,并设置相关参数,
2、创建Mesh,将上面定义的几何体和材质作为参数传入
3、设置Mesh的位置并添加到屏幕

const font = loader.load( // font资源URL 'fonts/helvetiker_regular.typeface.json', // onLoad回调 function (font) { const geometry = new TextGeometry('你好 hello',{ font:font, size:0.25, // Float。字体大小,默认值为100。 height:0.05, // Float。挤出文本的厚度。默认值为50。 curveSegments: 12, // Integer (表示文本的)曲线上点的数量。默认值为12。 bevelEnabled: true, // Boolean 是否开启斜角,默认为false。 bevelThickness: 0.01, // Float。文本上斜角的深度,默认值为20。 bevelSize: 0,// Float。斜角与原始文本轮廓之间的延伸距离。默认值为8。 bevelSegments: 3 // Integer 斜角的分段数。默认值为3。 }) const textMesh1 = new THREE.Mesh(geometry,materials) textMesh1.position.set(0,0,0) scene.add(textMesh1) } )

在init()函数中调用initFont()方法

在init()函数中调用initFont()方法,刷新浏览器看效果
Threejs进阶之十一:使用FontLoader和TextGeometry创建三维文字,在这里插入图片描述,第4张

获取文字宽度并向左偏移

我们得到的是从原点开始的一个三维文字,如果我们想要让这个文字的中心与原点重合,即将文字向左偏移一般,应该如何处理呢?
这里我们可以借助Geometry的.computeBoundingBox () 方法,该方法用于计算当前几何体的的边界矩形,该 *** 作会更新已有 .boundingBox。这里注意,边界矩形不会默认计算,我们需要调用该接口指定计算边界矩形,否则保持默认值 null
我们在使用时,首先调用geometry.computeBoundingBox ()方法,然后在geometry.boundingBox属性中获取max和min对应的x、y、z的值,我们根据最大值的x和最小值的x的差值来获取文字边界的长度,从而获取偏移量

geometry.computeBoundingBox() // console.log(geometry.boundingBox); const xOffset = (geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2 const textMesh1 = new THREE.Mesh(geometry,materials) textMesh1.position.set(-xOffset,0,0) scene.add(textMesh1)

Threejs进阶之十一:使用FontLoader和TextGeometry创建三维文字,在这里插入图片描述,第5张

添加中文

前面我们提到,要想创建三维的中文文字,需要支持中文的字体的json格式字体文件,我们前面也介绍了如何将ttf文件转换为json格式的字体文件,这里我们将转换好的简体中文直接使用

const font = loader.load( // font资源URL 'fonts/KaiTi_Regular.json', // onLoad回调 function (font) { console.log(font); const geometry = new TextGeometry('欢迎',{ font:font, size:0.25, // Float。字体大小,默认值为100。 height:0.08, // Float。挤出文本的厚度。默认值为50。 curveSegments: 12, // Integer (表示文本的)曲线上点的数量。默认值为12。 bevelEnabled: true, // Boolean 是否开启斜角,默认为false。 bevelThickness: 0.01, // Float。文本上斜角的深度,默认值为20。 bevelSize: 0,// Float。斜角与原始文本轮廓之间的延伸距离。默认值为8。 bevelSegments: 3 // Integer 斜角的分段数。默认值为3。 }) geometry.computeBoundingBox() // console.log(geometry.boundingBox); const xOffset = (geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2 const textMesh1 = new THREE.Mesh(geometry,materials) textMesh1.position.set(-xOffset,0,0) scene.add(textMesh1) } )

让文字产生倒影效果

要产生倒影效果的三维文字,我们可以在添加一个文字Mesh,将其沿x轴旋转180度,这样就得到了文字的倒影
旋转后得到的文字与原文字在z轴上有偏差,对其进行微调

geometry.computeBoundingBox() const xOffset = (geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2 const textMesh1 = new THREE.Mesh(geometry,materials) textMesh1.position.set(-xOffset,0,0) scene.add(textMesh1) const textMesh2 =new THREE.Mesh(geometry,materials) // console.log(geometry.boundingBox); textMesh2.position.set(-xOffset,-geometry.boundingBox.min.y-0.03,geometry.boundingBox.max.z-0.01) textMesh2.rotation.x = Math.PI scene.add(textMesh2)

Threejs进阶之十一:使用FontLoader和TextGeometry创建三维文字,在这里插入图片描述,第6张
好了,这次就写到这里吧,祝小伙伴们劳动节快乐!喜欢的关注点赞收藏吧

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/13518058.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-12-16
下一篇 2023-12-23

发表评论

登录后才能评论

评论列表(0条)

保存