今天郭先生說一下如何在three中顯示中文字體,而後結合tween實現文字位置的動畫。線案例請點擊博客原文。git
咱們都使用過three.js的FontLoader加載typeface.json實現font的使用,可是不少案例都是英文字體,那麼如何來生成中文字體呢?如今咱們能夠經過Facetype.js實現ttf向typeface.json的轉換。
首先咱們在網上下載ttf中文字體(或者在電腦的C:\Windows\Fonts直接複製一份中文的ttf字體),而後咱們登錄Facetype.js網站,選中準備好的ttf文件,點擊convert便可。獲得的json文件就可使用FontLoader加載了,其實仍是挺簡單的,中文ttf通常都比較大,因此在選擇喜歡字體的同時,也要考慮好文件的大小。github
以前也說過tween動畫,不過我以爲挺有意思的,咱們就拿百家姓來做文字素材。json
效果就是這樣的,咱們讓tween實現從圖一到圖二到圖三再到圖一的動畫,每一個漢字除了位置的變化還有朝向(lookAt)的變化。這裏的lookAt方法就是設置物體的朝向。好了開始上代碼。函數
圖一中點的位置能夠在平面幾何體中取點字體
let vertices1 = new THREE.PlaneGeometry(1400, 900, 13, 6).vertices;
他們的朝向相對於每一個字來講都是Vector3(0, 0, 1),因此能夠設置爲動畫
d.position.clone().add(Vector3(0, 0, 1)) //這裏的d.position就是每一個點的位置
圖二中點的位置能夠在球體中獲取網站
let vertices2 = new THREE.SphereGeometry(500, 12, 9).vertices;
他們的朝向很容易找,就是朝向中心點就能夠Vector3(0, 0, 0)
圖三中的點能夠經過計算獲得,就是一組旋轉上升的點this
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)); }
他們的朝向能夠設置爲spa
new THREE.Vector3(0, d.position.y, 0) //d.position.y就是點的y座標
這樣就設置好了點,接下來就製做動畫code
首先初始化三個動畫
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方法
function onUpdate() { let time = this._object.time; //動畫時刻值 if(flag == 0) {//這裏有三段動畫flag判斷是那一段動畫 group.children.forEach((d, i) => {//group裏面包含着全部文字網格 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))); }) } }
最後經過點擊觸發
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; },
這裏注意,因爲點擊切換的時候動畫上一個動畫可能沒有完成,因此先調用stop方法,讓動畫先停下來。別忘了在render函數中調用TWEEN.update(),否則動畫是不會執行的。
轉載請註明地址:郭先生的博客