今天郭先生說一下如何在three中顯示中文字體,然后結(jié)合tween實現(xiàn)文字位置的動畫。線案例請點擊chinese-font,
1. 生成中文字體
我們都使用過three.js的FontLoader加載typeface.json實現(xiàn)font的使用,但是很多案例都是英文字體,那么如何來生成中文字體呢?現(xiàn)在我們可以通過Facetype.js實現(xiàn)ttf向typeface.json的轉(zhuǎn)換。 首先我們在網(wǎng)上下載ttf中文字體(或者在電腦的C:\Windows\Fonts直接復(fù)制一份中文的ttf字體),然后我們登陸Facetype.js網(wǎng)站,選中準(zhǔn)備好的ttf文件,點擊convert即可。得到的json文件就可以使用FontLoader加載了,其實還是挺簡單的,中文ttf一般都比較大,所以在選擇喜歡字體的同時,也要考慮好文件的大小。
2. tween操作文字動畫
之前也說過tween動畫,不過我覺得挺有意思的,我們就拿百家姓來作文字素材。
效果就是這樣的,我們讓tween實現(xiàn)從圖一到圖二到圖三再到圖一的動畫,每個漢字除了位置的變化還有朝向(lookAt)的變化。這里的lookAt方法就是設(shè)置物體的朝向。好了開始上代碼。
1.設(shè)置點的位置和朝向
圖一中點的位置可以在平面幾何體中取點
1
|
let vertices1 = new THREE.PlaneGeometry(1400, 900, 13, 6).vertices; |
他們的朝向相對于每個字來說都是Vector3(0, 0, 1),所以可以設(shè)置為
1
|
d.position.clone().add(Vector3(0, 0, 1)) //這里的d.position就是每個點的位置 |
圖二中點的位置可以在球體中獲取
1
|
let vertices2 = new THREE.SphereGeometry(500, 12, 9).vertices; |
他們的朝向很容易找,就是朝向中心點就可以Vector3(0, 0, 0) 圖三中的點可以通過計算得到,就是一組旋轉(zhuǎn)上升的點
1
2
3
4
5
6
|
for (let i=0; i<98; i++) { let x = Math.sin(Math.PI / 12 * i) * 400; let y = (49 - i) * 8; let z = Math.cos(Math.PI / 12 * i) * 400; positions3.push( new THREE.Vector3(x,y,z)); } |
他們的朝向可以設(shè)置為
1
|
new THREE.Vector3(0, d.position.y, 0) //d.position.y就是點的y坐標(biāo) |
這樣就設(shè)置好了點,接下來就制作動畫
2.tween動畫
首先初始化三個動畫
1
2
3
4
5
6
7
8
9
10
11
12
|
initTween() { var pos = { time: 0 }; tween1 = new TWEEN.Tween(pos).to({ time: 1 }, 1000 ); tween2 = new TWEEN.Tween(pos).to({ time: 2 }, 1000 ); tween3 = new TWEEN.Tween(pos).to({ time: 0 }, 1000 ); tween1.easing(TWEEN.Easing.Linear.None); tween2.easing(TWEEN.Easing.Linear.None); tween3.easing(TWEEN.Easing.Linear.None); tween1.onUpdate(onUpdate); tween2.onUpdate(onUpdate); tween3.onUpdate(onUpdate); } |
這里的easing是動畫的緩動效果里面有很多種,不妨打印出來看一下
然后就是onUpdate方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
function onUpdate() { let time = this ._object.time; //動畫時刻值 if (flag == 0) { //這里有三段動畫flag判斷是那一段動畫 group.children.forEach((d, i) => { //group里面包含著所有文字網(wǎng)格 d.position.copy(positions3[i].clone().multiplyScalar(time / 2).add(positions1[i].clone().multiplyScalar(1 - time / 2))); d.lookAt(( new THREE.Vector3(0, d.position.y, 0).multiplyScalar(time / 2)).add(d.position.clone().add(lookAt1).multiplyScalar(1 - time / 2))); }) } else if (flag == 1) { group.children.forEach((d, i) => { d.position.copy(positions1[i].clone().multiplyScalar(1 - time).add(positions2[i].clone().multiplyScalar(time))); d.lookAt((d.position.clone().add(lookAt1).multiplyScalar(1 - time)).add(lookAt2.multiplyScalar(time))); }) } else if (flag == 2) { group.children.forEach((d, i) => { d.position.copy(positions2[i].clone().multiplyScalar(2 - time).add(positions3[i].clone().multiplyScalar(time - 1))); d.lookAt((lookAt2.multiplyScalar(2 - time)).add( new THREE.Vector3(0, d.position.y, 0).multiplyScalar(time - 1))); }) } } |
最后通過點擊觸發(fā)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
click() { tween1.stop(); tween2.stop(); tween3.stop(); if (flag == 0) { tween1.start(); } else if (flag == 1) { tween2.start(); } else if (flag == 2) { tween3.start(); } flag = (flag + 1) % 3; }, |
這里注意,由于點擊切換的時候動畫上一個動畫可能沒有完成,所以先調(diào)用stop方法,讓動畫先停下來。別忘了在render函數(shù)中調(diào)用TWEEN.update(),不然動畫是不會執(zhí)行的。
總結(jié)
到此這篇關(guān)于three.js顯示中文字體與tween應(yīng)用的文章就介紹到這了,更多相關(guān)three.js顯示中文字體與tween應(yīng)用內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
版權(quán)聲明:本文為郭志強(qiáng)的原創(chuàng)文章,原文鏈接:https://www.mrguo.link