天天看點

Three.js學習之路(二丶旋轉動畫/三維操作旋轉縮放/幾何體)

1.旋轉動畫、requestAnimationFrame周期性渲染

上節初篇就畫了個正方體,看起來沒什麼感覺,是以下面我大概介紹一下這個模型怎麼才能旋轉起來,讓事情變得有趣一些

function render() {
    renderer.render(scene,camera);//執行渲染操作
    mesh.rotateY(0.01);//每次繞y軸旋轉0.01弧度
}
//間隔20ms周期性調用函數fun,20ms也就是重新整理頻率是50FPS(1s/20ms),每秒渲染50次
setInterval(render,20);
           

把上節的renderer.render(scene,camera),替換成上面的代碼就可以實作模型自己旋轉,這個大概還有第二種方式實作旋轉吧,如下

function render() {
    renderer.render(scene,camera);//執行渲染操作
    mesh.rotateY(0.01);//每次繞y軸旋轉0.01弧度
    requestAnimationFrame(render);//請求再次執行渲染函數render
}
render();
           

嗯,這個方法一般預設保持60FPS的頻率,大約每16.7ms調用一次requestAnimationFrame()方法指定的函數,60FPS是理想的情況下,如果渲染的場景比較複雜或者說硬體性能有限可能會低于這個頻率,所有下面的可以真正實作勻速旋轉,嗯,是的,勻速!

let T0: any = new Date();//上次時間
function render() {
    let T1: any = new Date();//本次時間
    let t = T1-T0;//時間差
    T0 = T1;//把本次時間指派給上次時間
    requestAnimationFrame(render);
    renderer.render(scene,camera);//執行渲染操作
    mesh.rotateY(0.001*t);//旋轉角速度0.001弧度每毫秒
}
render();
           

2.滑鼠操作三維場景(旋轉/縮放)

上面介紹了怎麼實作旋轉,但是我們一般還要自己選角度,不是說模型自己旋轉到哪就看哪,這就非常被動,是以我們需要主動一點,我們添加個滑鼠操作,會不會更好一點呢。來吧!

function render() {
  renderer.render(scene,camera);//執行渲染操作
}
render();
var controls = new THREE.OrbitControls(camera,renderer.domElement);//建立控件對象
controls.addEventListener('change', render);//監聽滑鼠、鍵盤事件
           

這個是正常模式,但是呢,這裡會報錯TypeError: THREE.OrbitControls is not a constructor,為什麼呢?這個是因為用npm 安裝的three.js裡面的确沒有OrbitControls,是以這個需要手動安裝一下

npm install three-orbitcontrols
           

安裝完之後,需要在需要用到的頁面/元件的頭部引入一下

然後把THREE.OrbitControls(camera,renderer.domElement)改成OrbitControls(camera,renderer.domElement)就行了

再換成requestAnimationFrame寫法把,不然感覺學了不用,有點扯呼。

function render() {
  renderer.render(scene,camera);//執行渲染操作
  // mesh.rotateY(0.01);//每次繞y軸旋轉0.01弧度
  requestAnimationFrame(render);//請求再次執行渲染函數render
}
render();
var controls = new OrbitControls(camera,renderer.domElement);//建立控件對象
// 已經通過requestAnimationFrame(render);周期性執行render函數,沒必要再通過監聽滑鼠事件執行render函數
// controls.addEventListener('change', render)
           

這大概就行了,咦,這裡我想了想,光源會跟着模型旋轉而旋轉,如果我需要實作光源永遠跟着相機不動,就像主角都會想一直在舞台燈光下那樣,下面我們一起來實作模型的主角夢想:

function render() {
  // 複制相機的坐标
  var vector = camera.position.clone();
  point.position.set(vector.x, vector.y, vector.z); //重置點光源位置
  renderer.render(scene, camera);//執行渲染操作
  // mesh.rotateY(0.01);//每次繞y軸旋轉0.01弧度
  requestAnimationFrame(render);//請求再次執行渲染函數render
}
render();
var controls = new OrbitControls(camera, renderer.domElement);//建立控件對象
           

這樣滑鼠無論轉到哪,光源都會在相機那裡,不會再跟着模型旋轉了。

夢想是實作了,但是為什麼我感覺沒啥用呢

3.幾何體類型

到這裡就有人會問,這個是正方體的,我想加圓球或者其他的模型呢,接着,下面就給大家看看怎麼添加其他類型的幾何體

//長方體 參數:長,寬,高
let geometry = new THREE.BoxGeometry(100, 100, 100);
// 球體 參數:半徑60  經緯度細分數40,40
let geometry = new THREE.SphereGeometry(60, 40, 40);
// 圓柱  參數:圓柱面頂部、底部直徑50,50   高度100  圓周分段數
let geometry = new THREE.CylinderGeometry(50, 50, 100, 25);
// 正八面體
let geometry = new THREE.OctahedronGeometry(50);
// 正十二面體
let geometry = new THREE.DodecahedronGeometry(50);
// 正二十面體
let geometry = new THREE.IcosahedronGeometry(50);
           
Three.js學習之路(二丶旋轉動畫/三維操作旋轉縮放/幾何體)

這裡還會有人問,我怎麼添加多個幾何體組成其他形狀呢?不要着急,下面就帶大家看看

//立方體網格模型
let geometry1 = new THREE.BoxGeometry(100, 100, 100);
let material1 = new THREE.MeshLambertMaterial({
  color: 0x0000ff
}); //材質對象Material
let mesh1 = new THREE.Mesh(geometry1, material1); //網格模型對象Mesh
scene.add(mesh1); //網格模型添加到場景中

//球體網格模型
let geometry2 = new THREE.SphereGeometry(60, 40, 40);
let material2 = new THREE.MeshLambertMaterial({
  color: 0xff00ff
});
let mesh2 = new THREE.Mesh(geometry2, material2); //網格模型對象Mesh
mesh2.translateY(120); //球體網格模型沿Y軸正方向平移120
scene.add(mesh2);

// 圓柱網格模型
let geometry3 = new THREE.CylinderGeometry(50, 50, 100, 25);
let material3 = new THREE.MeshLambertMaterial({
  color: 0xffff00
});
let mesh3 = new THREE.Mesh(geometry3, material3); //網格模型對象Mesh
// mesh3.translateX(120); //球體網格模型沿Y軸正方向平移120
mesh3.position.set(120, 0, 0);//設定mesh3模型對象的xyz坐标為120,0,0
scene.add(mesh3); 
           
Three.js學習之路(二丶旋轉動畫/三維操作旋轉縮放/幾何體)

當然這裡可以自己自由發揮,想要什麼東西,自己可以慢慢研究,我就簡單示範一下。

不知道有沒有人發現我的圖檔有XYZ軸,這個東西不是預設有的,需要自己手動添加的,關鍵代碼我給出來,需要的可以加上,不需要的了解一下也是可以的

// 輔助坐标系  參數250表示坐标系大小,可以根據場景大小去設定
let axisHelper = new THREE.AxisHelper(250);//換成THREE.AxesHelper(250)
scene.add(axisHelper);
           

這裡也有個注意的就是AxisHelper是舊版的,新版的要用AxesHelper,如果用axisHelper沒報錯就不用管了

繼續閱讀