第二課threejs模型場景控制器

##?

>?背景:?創(chuàng)建出threejs?3D場景后如何使用鼠標操作場景內(nèi)模型元素助泽?啰扛,如拖動,放大縮小嗡贺,平移隐解,點擊觸發(fā)交互等。诫睬。煞茫。

####?安裝threejs控制器組件

```js

npm?install?three-orbitcontrols?-D

```

####?第一步

>?創(chuàng)建盛放場景盒子div

```js

<template>

??<div?class="three-box-one">

????<div?id="threeone"?/>

??</div>

</template>

```

####?第二步

>?引入vue,?threejs?,?three-orbitcontrols

```js

import?Vue?from?'vue';

import?*?as?THREE?from?'three';

import?*?as?OrbitControls?from?'three-orbitcontrols'

```

####?第三步

>?創(chuàng)建基礎(chǔ)的data數(shù)據(jù)

```js

data?():?DataType?{

??return?{

????id:?null,

????domW:?0,

????domH:?0,

????scene:?null,

????camera:?null,

????renderer:?null,

????mesh:?null,

????controls:?null

??}

},

```

####?第四步

>?初始運行創(chuàng)建場景,獲取場景寬度高度

```js

mounted?()?{

??//?獲取盛放場景div標簽

??this.id?=?document.getElementById('threeone')

??//?獲取盛放標簽寬高

??this.domW?=?this.id.offsetWidth

??this.domH?=?this.id.offsetHeight

??//?運行創(chuàng)建場景函數(shù)

??this.init()

},

```

####?第五步

>?創(chuàng)建場景函數(shù)講解

??--?1.?知識點講解?---

??a.?`new?THREE.PerspectiveCamera(45,?this.domW?/?this.domH,?0.01,?20000)`

????//?設(shè)置相機?45?攝像機視錐體垂直視野角度摄凡,?

????//?this.domW?/?this.domH?攝像機視錐體長寬比

????//?0.01?攝像機視錐體近端面(攝像機拍攝最近距離)

????//?20000?攝像機拍攝最遠距離续徽,超出距離模型場景不顯示


??b.?`new?THREE.WebGLRenderer({?antialias:?true,?alpha:?true?})`

????```js

????WebGLRenderer(?parameters?:?Object?)

????//?canvas?-?一個供渲染器繪制其輸出的canvas?它和下面的domElement屬性對應(yīng)。?如果沒有傳這個參數(shù)亲澡,會創(chuàng)建一個新canvas

????//?context?-?可用于將渲染器附加到已有的渲染環(huán)境(RenderingContext)中钦扭。默認值是null

????//?precision?-?著色器精度.?可以是?"highp",?"mediump"?或者?"lowp".?如果設(shè)備支持,默認為"highp"?

????//?alpha?-?canvas是否包含alpha?(透明度)床绪。默認為?false

????//?antialias?-?是否執(zhí)行抗鋸齒土全。默認為false.?避免模型渲染出現(xiàn)鋸齒現(xiàn)象

????//?stencil?-?繪圖緩存是否有一個至少8位的模板緩存(stencil?buffer)捎琐。默認為true

????//?preserveDrawingBuffer?-是否保留緩緩存直到手動清除或被覆蓋。?默認false.

????//?depth?-?繪圖緩存是否有一個至少6位的深度緩存(depth?buffer?)裹匙。?默認是true.

????//?logarithmicDepthBuffer?-?是否使用對數(shù)深度緩存。如果要在單個場景中處理巨大的比例差異末秃,就有必要使用概页。

????```

>?init?函數(shù)講解

??```js

????init?()?{

??????//?實例化場景函數(shù)

??????this.scene?=?new?THREE.Scene()

??????//?設(shè)置相機

??????this.camera?=?new?THREE.PerspectiveCamera(45,?this.domW?/?this.domH,?0.01,?20000)

??????//?攝像機z軸位置

??????this.camera.position.z?=?800

??????//?this.camera.position.y?=?100

??????//?實例化渲染器

??????this.renderer?=?new?THREE.WebGLRenderer({

????????antialias:?true,

????????alpha:?true

??????})

??????//?設(shè)置渲染器寬高

??????this.renderer.setSize(this.domW,?this.domH)

??????//將渲染器append到div容器中

??????this.id.appendChild(this.renderer.domElement)

??????//?添加燈光

??????this.addLight()

??????//?添加輔助線

??????this.axisHelper()

??????//?創(chuàng)建正方體

??????this.initBox()

??????//?刷幀渲染動畫

??????this.animate()

??????//?響應(yīng)屏幕改變大小函數(shù)

??????this.onWindowResize()

??????//?場景控制器函數(shù)

??????this.controlsFn()

????},

??```

??####?第五步

??>?添加燈光

??```js

??addLight?()?{

??????//?設(shè)置環(huán)境光

??????const?ambientLight?=?new?THREE.AmbientLight('#ffffff')

??????this.scene.add(ambientLight)

??????//?設(shè)置平行光

??????const?light?=?new?THREE.DirectionalLight('#ffffff')

??????this.scene.add(light)

??????//?設(shè)置點光源

??????const?pointLight?=?new?THREE.PointLight('#ffffff',?0.1,?1000)

??????pointLight.position.set(300,?300,?300)

??????this.scene.add(pointLight)

????},

??```

??####?第六步

??>?添加空間輔助線

??```js

??axisHelper?()?{

??????//?空間輔助線函數(shù)

??????const?axes:THREE.AxesHelper?=?new?THREE.AxesHelper(800)

??????this.scene.add(axes)

??},

??```

??####?第七步

??>?創(chuàng)建正方體和網(wǎng)格圓球

????--?1.?創(chuàng)建球體知識點?--

????a.?`new?THREE.SphereGeometry()`

????```js

??????new?THREE.SphereGeometry(radius?:?Float,?widthSegments?:?Integer,?heightSegments?:?Integer,?phiStart?:?Float,?phiLength?:?Float,?thetaStart?:?Float,?thetaLength?:?Float)


??????//?radius?—?球體半徑,默認為1练慕。

??????//?widthSegments?—?水平分段數(shù)(沿著經(jīng)線分段)惰匙,最小值為3,默認值為8铃将。

??????//?heightSegments?—?垂直分段數(shù)(沿著緯線分段)项鬼,最小值為2,默認值為6劲阎。

??????//?phiStart?—?指定水平(經(jīng)線)起始角度绘盟,默認值為0。

??????//?phiLength?—?指定水平(經(jīng)線)掃描角度的大小悯仙,默認值為?Math.PI?*?2龄毡。

??????//?thetaStart?—?指定垂直(緯線)起始角度,默認值為0锡垄。

??????//?thetaLength?—?指定垂直(緯線)掃描角度大小沦零,默認值為?Math.PI。

??????//?該幾何體是通過掃描并計算圍繞著Y軸(水平掃描)和X軸(垂直掃描)的頂點來創(chuàng)建的货岭。?因此路操,不完整的球體(類似球形切片)可以通過為phiStart,phiLength千贯,thetaStart和thetaLength設(shè)置不同的值來創(chuàng)建屯仗,?以定義我們開始(或結(jié)束)計算這些頂點的起點(或終點)。


????```

>?initBox?函數(shù)講解

```js

initBox?()?{

??//?添加正方體

??const?geometry?=?new?THREE.BoxGeometry(200,?200,?200)

??//?添加正方體材質(zhì)

??const?material?=?new?THREE.MeshBasicMaterial({?color:?'#ffffff',?map:?new?THREE.TextureLoader().load('https://www.douchuanwei.com/api/files/img/1.jpeg')?})

??//?合成正方體mesh網(wǎng)格

??this.mesh?=?new?THREE.Mesh(geometry,?material)

??this.scene.add(this.mesh)

??//?創(chuàng)建球體

??const?geometry2?=?new?THREE.SphereGeometry(60,?20,?60)

??//?創(chuàng)建球體材質(zhì)

??const?material2?=?new?THREE.MeshLambertMaterial({

????color:?'red',

????wireframe:?true

????//?emissive:0xad1919,

????//?vertexColors:?THREE.NoColors

????//?specular:0x4488ee,

????//?shininess:?12

??})

??//?將球體和材質(zhì)添加到mesh網(wǎng)格

??const?mesh2?=?new?THREE.Mesh(geometry2,?material2)

??//?球體從中心點向x軸平移250

??mesh2.translateX(250)

??this.scene.add(mesh2)

??//?創(chuàng)建第二個球體

??const?geometry3?=?new?THREE.SphereGeometry(60,?20,?60)

??const?material3?=?new?THREE.MeshLambertMaterial({

????color:?'red',?//?紅色球體

????wireframe:?true?//?將球體變成網(wǎng)格

????//?emissive:0xad1919,

????//?vertexColors:?THREE.NoColors

????//?specular:0x4488ee,

????//?shininess:?12

??})

??const?mesh3?=?new?THREE.Mesh(geometry3,?material3)

??mesh3.translateX(-250)

??this.scene.add(mesh3)

},

```

####?第八步

>?幀渲染動畫丈牢,讓場景動起來

```js

animate?()?{

??window.requestAnimationFrame(this.animate)

??//?正方體旋轉(zhuǎn)

??this.mesh.rotation.y?+=?0.02

??this.mesh.rotation.x?+=?0.01

??//?場景旋轉(zhuǎn)

??this.scene.rotation.y?+=?0.01

??this.renderer.render(this.scene,?this.camera)

}

```

####?第九步

>?啟用場景控制器

```js

controlsFn?()?{

??//?tslint:disable-next-line

??this.controls?=?new?OrbitControls(this.camera,?this.renderer.domElement)

},

```

####??controls?知識點

```js

controls.enablePan?=?false;?//禁止右鍵拖拽

controls.enableZoom?=?false;//禁止縮放

controls.enableRotate?=?false;?//禁止旋轉(zhuǎn)

controls.minZoom?=?0.5;?//?最小縮放比例

controls.maxZoom?=?2;?//?放大最大比例

//?上下旋轉(zhuǎn)范圍

controls.minPolarAngle?=?0;

controls.maxPolarAngle?=?Math.PI;

//?左右旋轉(zhuǎn)范圍

controls.minAzimuthAngle?=?-Math.PI?*?(100?/?180);

controls.maxAzimuthAngle?=?Math.PI?*?(100?/?180);

//將其設(shè)為true祭钉,以自動圍繞目標旋轉(zhuǎn)。請注意己沛,如果它被啟用慌核,你必須在你的動畫循環(huán)里調(diào)用.update()。

controls.autoRotate?=?true

//?當.autoRotate為true時申尼,圍繞目標旋轉(zhuǎn)的速度將有多快垮卓,默認值為2.0,相當于在60fps時每旋轉(zhuǎn)一周需要30秒师幕。

controls.autoRotateSpeed?=?2

//?當使用鍵盤按鍵的時候呀页,相機平移的速度有多快。默認值為每次按下按鍵時平移7像素拷姿。

controls.keyPanSpeed?=?7

//?這一對象包含了用于控制相機平移的按鍵代碼的引用寸癌。默認值為4個箭頭(方向)鍵。

controls.keys?=?{

??LEFT:?'ArrowLeft',?//left?arrow

??UP:?'ArrowUp',?//?up?arrow

??RIGHT:?'ArrowRight',?//?right?arrow

??BOTTOM:?'ArrowDown'?//?down?arrow

}

//?移除所有的事件監(jiān)聽

controls.dispose?()?

//?為指定的DOM元素添加按鍵監(jiān)聽稽寒。推薦將window作為指定的DOM元素。

controls.listenToKeyEvents(?domElement?:?HTMLDOMElement?)?

//?更新控制器。必須在攝像機的變換發(fā)生任何手動改變后調(diào)用空镜,或如果.autoRotate或.enableDamping被設(shè)置時,在update循環(huán)里調(diào)用捌朴。

controls.update?()

```

####?完整代碼示例

```js

<template>

??<div?class="three-box-one">

????<div?id="threeone"?/>

??</div>

</template>

<script?lang="ts">

import?Vue?from?'vue';

import?*?as?THREE?from?'three';

import?*?as?OrbitControls?from?'three-orbitcontrols'

interface?DataType?{

????id:?HTMLElement?|?null?|?Object?|?any;

????domW:?Number?|?any;

????domH:?Number?|?any;

????scene:?THREE.Scene?|?null?|?any;

????camera:?THREE.Camera?|?null?|?any;

????renderer:?THREE.Renderer?|?null?|?any;

????mesh:?THREE.Mesh?|?any;

????controls:?null?|?any;

}

export?default?Vue.extend({

??name:?'ThreeTwo',

??layout:?'threelayout',

??data?():?DataType?{

????return?{

??????id:?null,

??????domW:?0,

??????domH:?0,

??????scene:?null,

??????camera:?null,

??????renderer:?null,

??????mesh:?null,

??????controls:?null

????}

??},

??mounted?()?{

????this.id?=?document.getElementById('threeone')

????this.domW?=?this.id.offsetWidth

????this.domH?=?this.id.offsetHeight

????this.init()

??},

??methods:?{

????init?()?{

??????this.scene?=?new?THREE.Scene()

??????this.camera?=?new?THREE.PerspectiveCamera(45,?this.domW?/?this.domH,?0.01,?20000)

??????this.camera.position.z?=?800

??????//?this.camera.position.y?=?100

??????this.renderer?=?new?THREE.WebGLRenderer({

????????antialias:?true,

????????alpha:?true

??????})

??????this.renderer.setSize(this.domW,?this.domH)

??????this.id.appendChild(this.renderer.domElement)

??????this.addLight()

??????this.axisHelper()

??????this.initBox()

??????this.animate()

??????this.onWindowResize()

??????this.controlsFn()

????},

????controlsFn?()?{

??????//?tslint:disable-next-line

??????this.controls?=?new?OrbitControls(this.camera,?this.renderer.domElement)

????},

????initBox?()?{

??????const?geometry?=?new?THREE.BoxGeometry(200,?200,?200)

??????const?material?=?new?THREE.MeshBasicMaterial({?color:?'#ffffff',?map:?new?THREE.TextureLoader().load('https://www.douchuanwei.com/api/files/img/1.jpeg')?})

??????this.mesh?=?new?THREE.Mesh(geometry,?material)

??????this.scene.add(this.mesh)

??????const?geometry2?=?new?THREE.SphereGeometry(60,?20,?60)

??????const?material2?=?new?THREE.MeshLambertMaterial({

????????color:?'red',

????????wireframe:?true

????????//?emissive:0xad1919,

????????//?vertexColors:?THREE.NoColors

????????//?specular:0x4488ee,

????????//?shininess:?12

??????})

??????const?mesh2?=?new?THREE.Mesh(geometry2,?material2)

??????mesh2.translateX(250)

??????this.scene.add(mesh2)

??????const?geometry3?=?new?THREE.SphereGeometry(60,?20,?60)

??????const?material3?=?new?THREE.MeshLambertMaterial({

????????color:?'red',

????????wireframe:?true

????????//?emissive:0xad1919,

????????//?vertexColors:?THREE.NoColors

????????//?specular:0x4488ee,

????????//?shininess:?12

??????})

??????const?mesh3?=?new?THREE.Mesh(geometry3,?material3)

??????mesh3.translateX(-250)

??????this.scene.add(mesh3)

????},

????addLight?()?{

??????const?ambientLight?=?new?THREE.AmbientLight('#ffffff')

??????this.scene.add(ambientLight)

??????const?light?=?new?THREE.DirectionalLight('#ffffff')

??????this.scene.add(light)

??????const?pointLight?=?new?THREE.PointLight('#ffffff',?0.1,?1000)

??????pointLight.position.set(300,?300,?300)

??????this.scene.add(pointLight)

????},

????axisHelper?()?{

??????const?axes:THREE.AxesHelper?=?new?THREE.AxesHelper(800)

??????this.scene.add(axes)

????},

????onWindowResize?()?{

??????window.onresize?=?()?=>?{

????????this.domH?=?this.id.offsetHeight

????????this.domW?=?this.id.offsetWidth

????????this.camera.aspect?=?this.domW?/?this.domH

????????this.camera.updateProjectionMatrix()

????????this.renderer.setSize(this.domW,?this.domH)

??????}

????},

????animate?()?{

??????window.requestAnimationFrame(this.animate)

??????this.mesh.rotation.y?+=?0.02

??????this.mesh.rotation.x?+=?0.01

??????this.scene.rotation.y?+=?0.01

??????this.renderer.render(this.scene,?this.camera)

????}

??}

});

</script>

```

```

[更多內(nèi)容請到小豆包》](https://www.douchuanwei.com/)

>?掃碼訪問小豆包

>?

![23_34de43370a343405db1b00359bb895cd.png](https://www.douchuanwei.com/api/files/2022-03-05/png/23_34de43370a343405db1b00359bb895cd.png)

###?掃碼關(guān)注小豆包公眾號

![小豆包公眾號.jpg](https://www.douchuanwei.com/api/files/2022-03-05/jpeg/小豆包公眾號.jpg)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吴攒,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子砂蔽,更是在濱河造成了極大的恐慌洼怔,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件左驾,死亡現(xiàn)場離奇詭異镣隶,居然都是意外死亡,警方通過查閱死者的電腦和手機什荣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門矾缓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稻爬,你說我怎么就攤上這事嗜闻。” “怎么了桅锄?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵琉雳,是天一觀的道長。 經(jīng)常有香客問我友瘤,道長翠肘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任辫秧,我火速辦了婚禮束倍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盟戏。我一直安慰自己绪妹,他們只是感情好,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布柿究。 她就那樣靜靜地躺著邮旷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蝇摸。 梳的紋絲不亂的頭發(fā)上婶肩,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天办陷,我揣著相機與錄音,去河邊找鬼律歼。 笑死民镜,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的苗膝。 我是一名探鬼主播殃恒,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辱揭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起病附,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤问窃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后完沪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體域庇,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年覆积,在試婚紗的時候發(fā)現(xiàn)自己被綠了听皿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡宽档,死狀恐怖尉姨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吗冤,我是刑警寧澤又厉,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站椎瘟,受9級特大地震影響覆致,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肺蔚,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一煌妈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宣羊,春花似錦璧诵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赞枕,卻和暖如春澈缺,著一層夾襖步出監(jiān)牢的瞬間坪创,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工姐赡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留莱预,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓项滑,卻偏偏與公主長得像依沮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子枪狂,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

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

  • 馬上就要畢業(yè)了危喉,實習(xí)進入了一個GIS公司,任務(wù)要求使用Threejs寫個漸變的發(fā)光半球小特效州疾,我完成后決定寫出這篇...
    gardenlike2閱讀 15,891評論 1 3
  • Threejs 為什么辜限? webGL太難用,太復(fù)雜严蓖! 但是現(xiàn)代瀏覽器都支持 WebGL 這樣我們就不必使用 Fla...
    強某某閱讀 6,065評論 1 21
  • ThreeJS 里元素如下: 1.場景(Scene):是物體薄嫡、光源等元素的容器, 2.相機(Camera):控制...
    _花閱讀 989評論 0 1
  • 下載對應(yīng)的js 包括案例 git clonegit@gitee.com:173970984/three.js.gi...
    獵人老A閱讀 2,890評論 0 0
  • 一步步帶你實現(xiàn)web全景看房——three.js canvas畫2d相信大家都很熟悉了,但3d世界更加炫酷毒姨。我們直...
    Jiao_0805閱讀 667評論 0 0