文章目錄
- Camera 相機
- PerspectiveCamera 透視相機
- 正交相機
- 用鼠標控制相機
- 大幅度轉動(可以看到后面)
- 控制組件
- FlyControls 飛行組件控制
- FirstPersonControls 第一人稱控制
- PointerLockControls 指針鎖定控制
- OrbitControls 軌道控制
- TrackballControls 軌跡球控制
- TransformControls 變換控制組件
- 拖拽組件
- 嘗試引入并使用控件:OrbitControls 軌道
- 導入
- DAMPING 阻尼
Camera 相機
以下是幾種常見的相機簡介
ArrayCamera
: 數組相機StereoCamera
:雙眼相機,可以使用兩個相機來渲染場景,類似 VR,以及雙人成行的屏幕分開的雙人游戲CubeCamera
:立方體相機,有 6 個相機,分別渲染 6 個面,ThreeJS 可以用它來渲染環境,貼圖,反射,折射陰影OrthographicCamera
:正交相機,RTS 游戲,相對于透視相機(透視相機更接近人眼的觀察效果)PerspectiveCamera
:透視相機
PerspectiveCamera 透視相機
參數如下圖所示
第一個參數是視野:建議的值在 45~75
如果視野足夠大的話,那么規則的立方體可能被擠壓變形,類似這樣的效果
第二個參數是:橫縱比,一般是畫布的長/寬
const sizes = {width: 800,height: 600
}const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
第三個和第四個參數 near
和 far
默認值是
1, 1000
,意味著:
任何比近處更近,或者比遠處更遠的物體,都不會顯示出來
選擇合適的取值范圍,如果遠端有山莊,山脈,云朵之類的,可以取合適的值來判斷是否渲染它們。
正交相機
正交相機有六個參數,前四個是位置,左右上下,第五個和第六個跟透視相機的參數類似,遠近的渲染
const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 100)
上面的形狀并不規則,因為渲染的比例不對,我們獲取
const aspectRatio = sizes.width / sizes.height
// Camera
// const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height)
const camera = new THREE.OrthographicCamera(-1 * aspectRatio, 1 * aspectRatio, 1, -1, 0.1, 100)
- 正交相機不受透視影響,能保證物體形狀不因深度而發生變化,適合 2D、UI、地圖等場景。
- 乘以 aspectRatio 讓視口匹配屏幕比例,確保物體不會在不同設備下發生拉伸變形。
- 如果你需要準確控制幾何形狀或在屏幕上保持形狀固定,正交相機是更好的選擇。
用鼠標控制相機
獲取坐標位置,并處理坐標值的范圍在 [-0.5, 0.5]
/*** Cursor*/
const cursor = {x: 0,y: 0,
}
window.addEventListener('mousemove', (event) => {cursor.x = event.clientX / sizes.width - 0.5cursor.y = event.clientY / sizes.height - 0.5console.log('cursor:>>', cursor)
})
之后再 tick 函數里更改相機的位置
const tick = () => {const elapsedTime = clock.getElapsedTime()// Update objects// mesh.rotation.y = elapsedTimecamera.position.x = cursor.x * 10camera.position.y = cursor.y * 10camera.lookAt(mesh.position )// Renderrenderer.render(scene, camera)// Call tick again on the next framewindow.requestAnimationFrame(tick)
}
但是這里會有奇怪的問題, 似乎 x 軸跟 y 軸的邏輯是反著的
所以改變一下 cursor.y 的值,整體取值負數,這樣x,y軸都是反方向的了
或者 x 軸取負數,這樣就是類似跟隨鼠標的效果
但是這樣有個問題:我看不到物體的后面,那么,如何才能看到后面呢?或者說讓相機旋轉起來
大幅度轉動(可以看到后面)
const tick = () => {const elapsedTime = clock.getElapsedTime()// Update objects// mesh.rotation.y = elapsedTimecamera.position.x = Math.sin(cursor.x * Math.PI * 2) * 3camera.position.z = Math.cos(cursor.x * Math.PI * 2) * 3camera.position.y = cursor.y * 5camera.lookAt(mesh.position)// Renderrenderer.render(scene, camera)// Call tick again on the next framewindow.requestAnimationFrame(tick)
}
控制組件
FlyControls 飛行組件控制
演示地址點我: https://threejs.org/examples/#misc_controls_fly
FirstPersonControls 第一人稱控制
https://threejs.org/examples/#webgl_geometry_terrain
PointerLockControls 指針鎖定控制
https://threejs.org/examples/#misc_controls_pointerlock
OrbitControls 軌道控制
https://threejs.org/examples/#misc_controls_orbit
TrackballControls 軌跡球控制
https://threejs.org/examples/#misc_controls_trackball
TransformControls 變換控制組件
https://threejs.org/examples/#misc_controls_transform
拖拽組件
https://threejs.org/examples/#misc_controls_drag
嘗試引入并使用控件:OrbitControls 軌道
導入
OrbitControls
它不在 THREE
這個變量中,需要手動的導入
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'const controls = new OrbitControls(camera, canvas)
兩句話,就可以有下圖的使用效果了
DAMPING 阻尼
拖拽的時候有些生澀,加入阻尼之后,會有一定的加速度
但是會有些奇怪,因為需要再每一幀上更新控件才能正常的顯現,在 tick 函數中添加更新 controls.update()