·場景搭建
使用npm或者其他獲取安裝three,就像npm i three,之后在需要演示模型的vue組件內import * as THREE from 'three',此時我們就可以創建場景scene、燈光light、鏡頭、幾何體等等開始渲染循環了
鏡頭控制是必要的,我們不會加載一個3D模型只為了看一面的剪影,從官網可以找到許多種控制器,本項目使用的是npm i three-orbitcontrols
import OrbitControls from 'three-orbitcontrols'
1 create(){ //創建場景 2 this.renderer = new THREE.WebGLRenderer(); 3 4 this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 5000 ) 5 this.camera.position.z = 160 6 this.camera.position.x = 0 7 this.camera.position.y = 0 8 9 this.scene = new THREE.Scene(); 10 this.scene.add(this.camera) 11 12 //鼠標控制鏡頭 13 this.controls = new OrbitControls(this.camera) 14 15 //創建一個環境燈光 16 var ambientLight = new THREE.AmbientLight( 0xffffff, 0.4 ); 17 this.scene.add( ambientLight ); 18 19 //創建一個點燈光 20 var pointLight = new THREE.PointLight( 0xffffff, 0.5 ); 21 22 //給相機添加光源 23 this.camera.add( pointLight ); 24 25 //渲染器樣式 26 this.renderer.setClearColor(new THREE.Color('black')); 27 this.renderer.setSize(window.innerWidth, window.innerHeight); 28 this.renderer.domElement.setAttribute("style"," height:100%;width: 100%;") 29 30 },
現在有了一個有燈光和控制器但沒有模型的場景,而且沒有掛載到頁面
·引入加載器
顯然,我們無法使用代碼建立所有的模型,盡管three提供了建立多種幾何體的強大功能讓我們可以以純代碼開發三維場景,但項目中仍需要three提供的多種3D模型文件的Loader.js來幫助我們將建模軟件生產的模型加載成可以添加到scene的object
你可能需要展示stl|obj|3ds|3mf|....等等文件類型,我們可以在已安裝的three路徑 “\node_modules\three\examples\js\loaders” 下找到所有已支持的類型加載器,如果你找到了3MFLoader.js但沒有看到3DSLoader.js,可以到threejs的官方示例下查找使用樣例,頁面右下角查看源代碼就會發現3ds加載器叫TDSLoader.js ;P
官方樣例統統使用head寫法引入js,這不適合vue,除非你的網站就只有這一個組件演示這一類模型(要知道vue大都是單頁面網站),按照不同文件類型按需加載對應的加載器js才是效率的使用方式,那么。。使用ES6提供的import()實現運行時加載
例如objloader.js,將文件從node_modules中移到用戶可以獲取到的路徑下(比如static),就可以按如下方式使用了
1 somefunction:(path){//模型文件url 2 ...... 3 import('@/static/OBJLoader.js').then(module => { 4 5 let Loader = new THREE.OBJLoader(); 6 7 that.loadermashs(Loader,path) //入口 8 9 }).catch(err => { 10 11 this.message = "加載器獲取失敗:"+err; 12 }); 13 } 14 15 16 onProgress( xhr ) { 17 18 if ( xhr.lengthComputable ) { 19 20 var percentComplete = xhr.loaded / xhr.total * 100; 21 22 //message承接加載進度 23 this.message = Math.round(percentComplete, 2) + '% 已加載' ; 24 } 25 }, 26 27 28 onError( xhr ) { 29 30 this.message = xhr; 31 }, 32 33 34 loadermashs(Loader,path){ 35 36 let that = this; 37 38 Loader.setPath(path); 39 40 Loader.load('', function(object) { 41 42 that.scene.add(object); //前面的函數准備好后最終在這里用到 43 44 }, that.onProgress, that.onError); 45 }, 46
注意:需要手動在OBJLoader.js中首行加入:var THREE = require('three')
e.g 編譯時warning:"export 'OBJLoader' (imported as 'THREE') was not found in 'three',是因為THREE.OBJLoader()關系是運行時建立的,怎么消除這個warning我也不知道。。·掛載與卸載
1 start(){//掛載到頁面開始循環 2 document.getElementById("hello").appendChild(this.renderer.domElement) 3 this.running = true; 4 5 this.animate() 6 }, 7 8 animate() { 9 10 this.renderer.render(this.scene, this.camera) 11 12 if(this.running) 13 requestAnimationFrame(this.animate)//再次調用animate 14 }
running作為關閉標識
webGL中,手動卸載是有必要的,按照開發者原意,系統判斷哪些資源可以廢棄是不可能的:用戶可能在某一幀放棄使用某個模型,也可能在下一幀重新啟用,因此自動丟棄不被使用的資源是不合理的,而不做手動處理的后果是當你多次打開演示后:
Error: WebGL: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one on...
所以請在關閉演示之前卸載他們:相關api
1 if(this.running){ 2 3 let canvas = document.getElementsByTagName('canvas')[0]; 4 5 if(canvas){ 6 let gl = canvas.getContext('webgl'); 7 8 canvas.addEventListener('webglcontextlost', function(e) { 9 //console.log(e); 10 }, false); 11 12 gl.getExtension('WEBGL_lose_context').loseContext(); 13 } 14 this.running = false 15 16 this.renderer.dispose(); 17 18 this.scene.dispose(); 19 20 this.controls.dispose(); 21 }
·其他
網頁應用的dialog中展示某obj模型,最終演示效果:

此外還有材質加載、貼圖、stl格式jzip問題等等。。有的坑我還沒踩只是遠遠的望了一下,如果同為初學者,那么希望能幫到你
如有見解還請大佬指教:D
