Three.js筆記(八)相機(jī)(2)

自定義控件

回到PerspectiveCamera透視相機(jī)上來任连。注釋OrthographicCamera正交相機(jī),取消注釋PerspectiveCamera透視相機(jī)茵休,移動相機(jī)曹鸠,使其面向立方體金砍,刪掉tick中的對網(wǎng)格體旋轉(zhuǎn)的部分。

// 相機(jī)

const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 1, 1000)

// const aspectRatio = sizes.width / sizes.height

// const camera = new THREE.OrthographicCamera(- 1 * aspectRatio, 1 * aspectRatio, 1, - 1, 0.1, 100)

// camera.position.x = 2

// camera.position.y = 2

camera.position.z = 3

camera.lookAt(mesh.position)

scene.add(camera)

以用鼠標(biāo)控制相機(jī)為例餐蔬,首先需要知道鼠標(biāo)坐標(biāo)碎紊∮痈剑可以使用原生JavaScript的偵聽事件addEventListener,來偵聽mousemove事件仗考。

坐標(biāo)將通過回調(diào)函數(shù)返回音同,比如event.clientX和event.clientY

// 鼠標(biāo)

window.addEventListener('mousemove', (event) =>

{

? ? console.log(event.clientX, event.clientY)

})

此處的返回值可以直接使用,但是調(diào)整下值的范圍會更好秃嗜,比如調(diào)整為區(qū)間為1的值权均。

比如,對于x:

? ? 當(dāng)光標(biāo)位于畫布左側(cè)锅锨,輸出-0.5

? ? 當(dāng)光標(biāo)位于畫布中間叽赊,輸出0

? ? 當(dāng)光標(biāo)位于畫布右側(cè),輸出0.5

當(dāng)然也可以采用其它值必搞。

仿照size變量必指,這里創(chuàng)建個cursor變量,變量默認(rèn)屬性包含x和y恕洲,當(dāng)觸發(fā)mousemove回調(diào)時塔橡,更新屬性的值

// 鼠標(biāo)

const cursor = {

? ? x: 0,

? ? y: 0

}

window.addEventListener('mousemove', (event) =>

{

? ? cursor.x = event.clientX / sizes.width - 0.5

? ? cursor.y = event.clientY / sizes.height - 0.5

? ? console.log(cursor.x, cursor.y)

})

event.clientX除以sizes.width會返回一個介于0~1之間的值,通過減去一個0.5霜第,讓值分布在0.5~-0.5

這樣葛家,就完成了鼠標(biāo)位置的存儲,并且可以通過tick更新位置庶诡。

const tick = () =>

{

? ? // ...

? ? // 更新相機(jī)

? ? camera.position.x = cursor.x

? ? camera.position.y = cursor.y

? ? // ...

}

運(yùn)行后惦银,會發(fā)現(xiàn)沿y軸運(yùn)動方向不對,這是因?yàn)門hree.js中positon.y向上運(yùn)動時為正末誓,在網(wǎng)頁中clientY向下運(yùn)動時為正扯俱。

通過在cursor.y上添加負(fù)號,來糾正喇澡。

window.addEventListener('mousemove', (event) =>

{

? ? cursor.x = event.clientX / sizes.width - 0.5

? ? cursor.y = - (event.clientY / sizes.height - 0.5)

})

可以通過cursor.x和cursor.y乘上一個數(shù)字迅栅,來調(diào)整幅度大小。此時仍可通過lookAt()方法調(diào)整相機(jī)朝向晴玖。

const tick = () =>

{

? ? // ...

? ? // 更新相機(jī)

? ? camera.position.x = cursor.x * 5

? ? camera.position.y = cursor.y * 5

? ? camera.lookAt(mesh.position)

? ? // ...

}

更進(jìn)一步读存,還可以通過使用Math.sin()和Math.cos()實(shí)現(xiàn)相機(jī)繞網(wǎng)格體旋轉(zhuǎn)。

同時使用cos和sin時呕屎,可以讓運(yùn)動變成圓周運(yùn)動让簿。要運(yùn)動成完成的圓,角度的大小必須是Π的2倍秀睛《保可以通過使用Math.PI,使用Π的值蹂安。

要增加圓的半徑椭迎,可以簡單的將Math.sin()和Math.cos()結(jié)果乘上一個數(shù)锐帜。

const tick = () =>

{

? ? // ...

? ? // 更新相機(jī)

? ? camera.position.x = Math.sin(cursor.x * Math.PI * 2) * 2

? ? camera.position.z = Math.cos(cursor.x * Math.PI * 2) * 2

? ? camera.position.y = cursor.y * 3

? ? camera.lookAt(mesh.position)

? ? // ...

}

tick()

這只是一個自定義控制的例子,Three.js內(nèi)置了許多控件類畜号,用來進(jìn)行許多的相似操作缴阎。

內(nèi)建控件

如果在Three.js文檔中搜索控件,會看到很多現(xiàn)成的控件简软。

DeviceOrientationControls設(shè)備陀螺儀控件

DeviceOrientationControls設(shè)備陀螺儀控件蛮拔,就是根據(jù)權(quán)限許可,依照設(shè)備方向相應(yīng)的旋轉(zhuǎn)相機(jī)痹升。如果設(shè)備合適语泽,可以用來創(chuàng)建全景圖或者VR效果。

FlyControls飛行控件

FlyControls飛行控件允許像飛船一樣控制相機(jī)视卢,此時可在三個軸上任意旋轉(zhuǎn)踱卵、并可前后移動。

FirstPersonControls第一人稱控件

FirstPersonControls第一人稱控件類似上一個据过,但具有一個固定向上的軸惋砂,即不能向前后左右翻轉(zhuǎn),雖然名字里有第一人稱绳锅,但是相機(jī)本身不含人西饵。

PointerLockControls指針鎖定控件

PointerLockControls指針鎖定控件使用了JavaScript的pointer lock API。通過這個鳞芙,隱藏了鼠標(biāo)指針眷柔,并使其居中,但仍在事件回調(diào)中繼續(xù)發(fā)送移動原朝。使用這個API驯嘱,可以創(chuàng)建FPS游戲,但是喳坠,這個API只提供了相機(jī)的旋轉(zhuǎn)鞠评,相機(jī)的移動和游戲中的物理效果仍舊需要自行處理。

OrbitControls環(huán)繞控件

OrbitControls環(huán)繞控件類似于上面的自定義控件的例子壕鹉√昊希可以通過左鍵繞某個點(diǎn)旋轉(zhuǎn),使用鼠標(biāo)右鍵橫向平移晾浴,使用滾輪放大縮小负乡。

TrackballControls軌跡球控件

TrackballControls軌跡球控件類似OrbitControls環(huán)繞控件,但是可以在豎直方向上翻轉(zhuǎn)脊凰。

TransformControls變換控件

TransformControls變換控件和相機(jī)無關(guān)抖棘。可以用它給對象添加一個控件,用來移動對象钉答。

這里只講OrbitControls環(huán)繞控件

OrbitControls環(huán)繞控件

注釋掉tick中更新相機(jī)的部分。

實(shí)例化

首先杈抢,使用OrbitControls類實(shí)例化變量数尿。

由于使用了Webpack,將會以以下形式引入

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

之后就可以直接實(shí)例化OrbitControls 類惶楼,但要在創(chuàng)建相機(jī)后執(zhí)行右蹦。

要使其正常工作,需要向其傳入相機(jī)和畫布歼捐,然后實(shí)例會自己處理鼠標(biāo)事件何陆。

// 控件

const controls = new OrbitControls(camera, canvas)

這樣就可以使用鼠標(biāo)左鍵或者右鍵來移動相機(jī),使用滾輪進(jìn)行縮放豹储。

比自定義控件方便得多贷盲,且?guī)в性S多控件。然后再往更深層次研究剥扣。

target目標(biāo)

默認(rèn)情況下巩剖,相機(jī)看向場景中心∧魄樱可以通過target目標(biāo)屬性修改它佳魔。

這個屬性是個Vector3,意思就是通過x晦炊、y鞠鲜、z三個屬性定義的。

如果希望OrbitControls環(huán)繞控件默認(rèn)查看立方體上方断国,只需要增加y值贤姆。

controls.target.y = 2

這個用處不是很大,先注釋掉它稳衬。

Damping阻尼

Damping阻尼通過加速度和摩擦力公式來平滑動畫庐氮。

要啟用阻尼,請將controls的enableDamping屬性設(shè)置為true宋彼。

為了正常運(yùn)行弄砍,還需要通過在每幀調(diào)用controls.update()∈涮椋可以通過tick()實(shí)現(xiàn)音婶。

// 控件

const controls = new OrbitControls(camera, canvas)

controls.enableDamping = true

// ...

const tick = () =>

{

? ? // ...

? ? // Update controls

? ? controls.update()

? ? // ...

}

這樣控件看起來更加流暢。

阻尼可以用在各種旋轉(zhuǎn)莱坎、移動衣式、縮放、角度控制上,甚至按鍵綁定上碴卧。

何時使用內(nèi)建控件

雖然這些控件很方便弱卡,但是都有局限性。如果過于依賴它們住册,可能需要以意想不到的方式改變類的工作方式婶博。

首先請確保所需的功能,然后檢查內(nèi)建控件的功能是否完全覆蓋所需的荧飞。

否則凡人,需要自己建立控件。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載叹阔,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者挠轴。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市耳幢,隨后出現(xiàn)的幾起案子岸晦,更是在濱河造成了極大的恐慌,老刑警劉巖睛藻,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件委煤,死亡現(xiàn)場離奇詭異,居然都是意外死亡修档,警方通過查閱死者的電腦和手機(jī)碧绞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吱窝,“玉大人讥邻,你說我怎么就攤上這事≡合浚” “怎么了兴使?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長照激。 經(jīng)常有香客問我发魄,道長,這世上最難降的妖魔是什么俩垃? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任励幼,我火速辦了婚禮,結(jié)果婚禮上口柳,老公的妹妹穿的比我還像新娘苹粟。我一直安慰自己,他們只是感情好跃闹,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布嵌削。 她就那樣靜靜地躺著毛好,像睡著了一般。 火紅的嫁衣襯著肌膚如雪苛秕。 梳的紋絲不亂的頭發(fā)上肌访,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機(jī)與錄音艇劫,去河邊找鬼吼驶。 笑死,一個胖子當(dāng)著我的面吹牛港准,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播咧欣,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼浅缸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了魄咕?” 一聲冷哼從身側(cè)響起衩椒,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哮兰,沒想到半個月后毛萌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喝滞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年阁将,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片右遭。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡做盅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窘哈,到底是詐尸還是另有隱情吹榴,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布滚婉,位于F島的核電站图筹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏让腹。R本人自食惡果不足惜远剩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骇窍。 院中可真熱鬧民宿,春花似錦、人聲如沸像鸡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至志群,卻和暖如春着绷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锌云。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工荠医, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桑涎。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓彬向,卻偏偏與公主長得像,于是被迫代替她去往敵國和親攻冷。 傳聞我的和親對象是個殘疾皇子娃胆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容