初識(shí)three.js,搭建three.js+vue.js項(xiàng)目(threejs vue3)

初識(shí)three.js,搭建three.js+vue.js項(xiàng)目(threejs vue3)

作者:前端藏經(jīng)閣

轉(zhuǎn)發(fā)鏈接:https://www.yuque.com/xwifrr/uxqg5v/ggxx2b

WebGL

簡(jiǎn)介:WebGL(全寫Web Graphics Library)是一種3D繪圖協(xié)議,這種繪圖技術(shù)標(biāo)準(zhǔn)允許把JavaScript和OpenGL ES 2.0(OpenGL for Embedded Systems,OpenGL嵌入式版本,針對(duì)手機(jī)、游戲機(jī)等設(shè)備相對(duì)較輕量級(jí)的版本)結(jié)合在一起,通過增加OpenGL ES 2.0的一個(gè)JavaScript綁定,WebGL可以為HTML5 Canvas提供硬件3D加速渲染,這樣Web開發(fā)人員就可以借助系統(tǒng)顯卡來在瀏覽器里更流暢地展示3D場(chǎng)景和模型了,還能創(chuàng)建復(fù)雜的導(dǎo)航和數(shù)據(jù)視覺化。

three.js

簡(jiǎn)介:Three.js是WebGL的JavaScript 3D庫,其對(duì)WebGL提供的接口進(jìn)行了非常好的封裝,簡(jiǎn)化了很多細(xì)節(jié),大大降低了學(xué)習(xí)成本,成為前端開發(fā)者完成3D繪圖的得力工具。

three.js官方文檔 :threejs.org/

three.js中文文檔 : https://techbrood.com/threejs/docs/

Three.js整體認(rèn)知(附:Three.js功能概覽)

初識(shí)three.js,搭建three.js+vue.js項(xiàng)目(threejs vue3)

一、threejs三大組件(場(chǎng)景-scene,相機(jī)-camera,渲染器-renderer)

場(chǎng)景(Scenes)

場(chǎng)景是所有物體的容器,場(chǎng)景只有一種。

場(chǎng)景的構(gòu)造函數(shù)是:

var scene = new THERR.Scene()復(fù)制代碼

Fog(線性霧):

scene.fog = new THREE.Fog(0xcce0ff, 10, 500)復(fù)制代碼

照相機(jī)(Cameras)

定義了三維空間到二維屏幕的投影方式,投影方式主要分為正交投影和透視投影。

1.正交投影:正交投影照相機(jī)獲得的結(jié)果對(duì)于在三維空間內(nèi)平行的線,投影到二維空間中也一定是平行的。

2.透視投影:透視投影照相機(jī)獲得的結(jié)果是類似人眼在真實(shí)世界中看到的有“近大遠(yuǎn)小”的效果。

初識(shí)three.js,搭建three.js+vue.js項(xiàng)目(threejs vue3)

一般說來,對(duì)于制圖、建模軟件通常使用正交投影,這樣不會(huì)因?yàn)橥队岸淖兾矬w比例;而對(duì)于其他大多數(shù)應(yīng)用,通常使用透視投影,因?yàn)檫@更接近人眼的觀察效果,以下詳細(xì)介紹透視投影。

透視投影照相機(jī)(Perspective Camera)的構(gòu)造函數(shù)是:

var camera = new THREE.PerspectiveCamera(fov, aspect, near, far)復(fù)制代碼

讓我們通過一張透視照相機(jī)投影的圖來了解這些參數(shù)。

初識(shí)three.js,搭建three.js+vue.js項(xiàng)目(threejs vue3)

透視圖中,灰色的部分是視景體,是可能被渲染的物體所在的區(qū)域,在該視景體以外的物體將不會(huì)被渲染。

fov是視景體豎直方向上的張角(是角度制而非弧度制),如側(cè)視圖所示。

aspect等于width / height,是照相機(jī)水平方向和豎直方向長度的比值,通常設(shè)為Canvas的橫縱比例。

near照相機(jī)到視景體最近的距離,為正值。

far照相機(jī)到視景體最遠(yuǎn)的距離,為正值。

渲染器(Renderers)

渲染器的作用就是將相機(jī)拍攝出的畫面在瀏覽器中呈現(xiàn)出來。渲染器決定了渲染的結(jié)果應(yīng)該畫在頁面的什么元素上面,并且以怎樣的方式來繪制。three.js中有很多種類的渲染器,例如webGLRenderer、canvasRenderer、SVGRenderer,通常使用的是webGLRenderer渲染器。 webGLRenderer渲染器的構(gòu)造函數(shù)是:

renderer = new THERR.WebGLRenderer()復(fù)制代碼

創(chuàng)建完渲染器之后,需要調(diào)用render方法將之前創(chuàng)建好的場(chǎng)景和相機(jī)相結(jié)合從而渲染出來,即調(diào)用渲染器的render方法:

renderer.render(scene,camera)復(fù)制代碼

了解了three.js完成3D繪圖的三大要素之后,便可以在頁面中創(chuàng)建場(chǎng)景,并利用相機(jī)將場(chǎng)景渲染到網(wǎng)頁上。

首先需要下載three.js庫,并引用到自己的代碼中,以下為三種引入方式,選擇合適的方式在自己的項(xiàng)目中。

<script src="lib/three.js"></script> //ES5const THREE=require('three') //CommonJS/AMDimport * as THREE from 'three' //ES6復(fù)制代碼

// 創(chuàng)建場(chǎng)景var scene = new THREE.Scene(); // 創(chuàng)建透視相機(jī)var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); // 創(chuàng)建一個(gè) WebGL 渲染器var renderer = new THREE.WebGLRenderer({ alpha: true,// 默認(rèn)情況下為黑色場(chǎng)景,此處設(shè)置為透明(即白色場(chǎng)景)}); // 設(shè)置渲染器為全屏renderer.setSize(window.innerWidth, window.innerHeight); // 添加到網(wǎng)頁中document.body.appendChild(renderer.domElement);復(fù)制代碼

完成上述各個(gè)步驟之后,我們?cè)诰W(wǎng)頁上看到的只有一塊靜態(tài)的白色場(chǎng)景,看不到任何東西,接下來通過一些基礎(chǔ)圖像的學(xué)習(xí)和了解,以呈現(xiàn)一些圖形效果。

二、圖像的表示

繪制的前期準(zhǔn)備工作已經(jīng)做完,接下來要做的就是把想要繪制的物體添加到場(chǎng)景中。在計(jì)算機(jī)世界中,3D世界是由點(diǎn)組成,兩個(gè)點(diǎn)能夠組成一條直線,三個(gè)不在一條直線上的點(diǎn)就能夠組成一個(gè)三角面片,無數(shù)個(gè)三角面片就能夠組成各種各樣形狀的物體,通常把這種網(wǎng)格模型叫做Mesh模型。Mesh模型是三維開發(fā)中使用的最為廣泛的型。

初識(shí)three.js,搭建three.js+vue.js項(xiàng)目(threejs vue3)

Geometries(幾何圖形)

three.js給出了很多方法去生成固定的網(wǎng)格形狀,比如長方體(BoxGeometry)、球體(SphereGeometry)、圓形(CircleGeometry)等等。還有根據(jù)具體坐標(biāo)生成具體形狀的方法,可以借助第三方建模軟件(SketchUp)建模之后導(dǎo)入,目前支持的模型格式有.obj(最常用),.dae,.ctm,.ply,.stl,.wrl,.vtk等。Three.js有一系列支持外部導(dǎo)入文件的函數(shù),是在three.js庫之外的,使用前需要單獨(dú)下載。(例如:OrbitControls-控制器、OBJLoader-加載.obj 文件、MTLLoader-加載.mtl文件)。

Materials(材質(zhì))

three.js給出了很多種直接生成材質(zhì)的方法,其中比較常用的有MeshBasicMaterial(對(duì)光照無感,給幾何體一種簡(jiǎn)單的顏色或顯示線框),MeshLambertMaterial(對(duì)光照有反應(yīng),無光源則不會(huì)顯示,用于創(chuàng)建暗淡的不發(fā)光的物體)、MeshPhongMaterial(對(duì)光照有反應(yīng),無光源不會(huì)顯示,用于創(chuàng)建金屬類米昂涼的物體)等等。物體之所以能被人眼看見,一種是它自身的材料就能發(fā)光,不需要借助外界光源;另一種是自身材料不發(fā)光,需要反射環(huán)境中的光。對(duì)于自身不發(fā)光的物體,需要個(gè)場(chǎng)景添加光源從而達(dá)到可視的效果。

Lights(燈光)

three.js中可以創(chuàng)建出很多不同類型的光源,比如環(huán)境光AmbientLight(它的顏色會(huì)添加到整個(gè)場(chǎng)景和所有對(duì)象的當(dāng)前顏色上),點(diǎn)光源PointLight(這種光源放出的光線來自同一點(diǎn),且輻射方向四面八方,如蠟燭發(fā)出的光),方向光DirectionalLight(也稱作無限光,從這種光源發(fā)出的光線可以看做是平行的,如太陽光),聚光燈SpotLight(這種光源的光線從一個(gè)椎體中射出,在被照射的物體上產(chǎn)生聚光的效果,如手電筒發(fā)出的光。)有光源就缺少不了陰影,在Three.js中,能形成陰影的光源只有DirectionalLight和SpotLight;而相對(duì)地,能表現(xiàn)陰影效果的材質(zhì)只有LambertMaterial和PhongMaterial。three.js中渲染陰影的開銷比較大,所以默認(rèn)物體是沒有陰影的,需要單獨(dú)開啟。開啟陰影的方法:

  • 將渲染器的shadowMapEnabled屬性設(shè)置為true(告訴渲染器可以渲染隱形)
  • 將物體及光源的castShadow屬性設(shè)置為true(告訴物體及光源可以透射陰影)
  • 將接收該陰影的物體的receiveShadow屬性設(shè)置為true(告訴物體可以接收其他物體的陰影)

在了解了關(guān)于圖形的基本知識(shí)之后,在上面的代碼的基礎(chǔ)上添加簡(jiǎn)單圖像。

var geometry = new THREE.BoxGeometry(1,1,1); // 創(chuàng)建一個(gè)長寬高都為1個(gè)單位的立方體var material = new THREE.MeshBasicMaterial({color: 0x00ff00}); // 創(chuàng)建材質(zhì),對(duì)光照無感var cube = new THREE.Mesh(geometry, material); // 創(chuàng)建一個(gè)立方體網(wǎng)格(mesh),將材質(zhì)包裹在立方體上scene.add(cube); // 將立方體網(wǎng)格添加到場(chǎng)景中camera.position.z = 5; // 指定相機(jī)位置function render() {requestAnimationFrame(render); // 讓瀏覽器執(zhí)行參數(shù)中的函數(shù),不斷循環(huán)(瀏覽器一個(gè)新的API)renderer.render(scene, camera); // 結(jié)合場(chǎng)景和相機(jī)進(jìn)行渲染,即用攝像機(jī)拍下此刻的場(chǎng)景}render();復(fù)制代碼

在render()函數(shù)中添加以下代碼使上面在場(chǎng)景中添加的正方體運(yùn)動(dòng)起來。

cube.rotation.x = 0.1;cube.rotation.y = 0.1;復(fù)制代碼

Controls(控制器)

軌道控制插件OrbitControls.js可以實(shí)現(xiàn)場(chǎng)景用鼠標(biāo)交互,讓場(chǎng)景動(dòng)起來,控制場(chǎng)景的旋轉(zhuǎn)、平移和縮放。由于OrbitControls.js是一個(gè)插件,所以在three.js 中使用時(shí),需要單獨(dú)引入該文件。

controls = new THREE.OrbitControls(camera);// 初始化控制器controls.target.set(0, 0, 0);// 設(shè)置控制器的焦點(diǎn),使控制器圍繞這個(gè)焦點(diǎn)進(jìn)行旋轉(zhuǎn)controls.minDistance = 80;// 設(shè)置移動(dòng)的最短距離(默認(rèn)為零)controls.maxDistance = 400;// 設(shè)置移動(dòng)的最長距離(默認(rèn)為無窮)controls.maxPolarAngle = Math.PI / 3;//繞垂直軌道的距離(范圍是0-Math.PI,默認(rèn)為Math.PI)controls.update();// 照相機(jī)轉(zhuǎn)動(dòng)時(shí),必須更新該控制器復(fù)制代碼

配置該插件之后實(shí)現(xiàn)的效果:

操控效果按住鼠標(biāo)左鍵并移動(dòng)攝像機(jī)圍繞場(chǎng)景中心旋轉(zhuǎn)轉(zhuǎn)動(dòng)鼠標(biāo)滑輪或按住中鍵并移動(dòng)放大或縮小按住鼠標(biāo)右鍵并移動(dòng)在場(chǎng)景中平移上、下、左、右方向鍵在場(chǎng)景中平移

Loaders(加載器)

用來加載不同格式的文件,主要介紹以下三種:

OBJLoader加載器(需要單獨(dú)引入js文件):用來加載.obj文件(分為有材質(zhì)和沒有材質(zhì)兩種)。

// 沒有材質(zhì)new THREE.OBJLoader().load('./tree.obj', function (obj) { obj.scale.set(10, 10, 10); obj.position.set(-10, 0, 0); obj.children.forEach(function (e) { e.castShadow = true});// 設(shè)置陰影 scene.add(obj)});復(fù)制代碼

MTLLoader加載器(需要單獨(dú)引入js文件):用來加載.mtl文件(即加載有材質(zhì)物體的obj文件之前先加載mtl文件)。

// 有材質(zhì)new THREE.MTLLoader().setPath('./model/VANS/').load('VANS.mtl', function (materials) { materials.preload(); new THREE.OBJLoader().setMaterials(materials).setPath('./model/VANS/').load('VANS.obj', function (obj) { obj.scale.set(0.8, 0.8, 0.8); obj.position.set(-40, -50, 10); scene.add(obj) })});復(fù)制代碼

CSS2DRenderer加載器(需要單獨(dú)引入js文件):如果要將基于HTML的標(biāo)簽與3D對(duì)象組合,則CSS2DRenderer渲染器非常有用。這里,各個(gè)DOM元素也被包裝到CSS2DObject的一個(gè)實(shí)例中并添加到場(chǎng)景圖中。

// 初始化 CSS2DRendererlabelRenderer = new THREE.CSS2DRenderer();labelRenderer.setSize(window.innerWidth, window.innerHeight); // 設(shè)置渲染器的大小labelRenderer.domElement.style.position = 'absolute';labelRenderer.domElement.style.top = 0;container.appendChild(labelRenderer.domElement);// 標(biāo)注實(shí)例function addSprite(text, Mash, callback) { biaozhudiv = document.createElement('div'); biaozhudiv.className = 'label'; biaozhudiv.textContent = text; biaozhudiv.onclick = function () { callback(Mash) }; biaozhuLabel = new THREE.CSS2DObject(biaozhudiv); biaozhuLabel.position.set(0, 0, 0); Mash.add(biaozhuLabel); }復(fù)制代碼

Textures(紋理)

紋理是一個(gè)2D圖片(甚至也有1D和3D的紋理),它可以用來添加物體的細(xì)節(jié);可以想象紋理是一張繪有磚塊的紙,無縫折疊貼合到你的3D的房子上,這樣你的房子看起來就像有磚墻外表了。

var textureCube = new THREE.CubeTextureLoader().load(urls);scene.background = textureCube;復(fù)制代碼

Three.js vue.js

1.用npm 安裝three npm install three?????

three.js 安裝地址 :https://www.npmjs.com/package/three

安裝成功后,在項(xiàng)目中 import three from 'three';,之后運(yùn)行程序。

發(fā)現(xiàn)控制臺(tái)報(bào)錯(cuò) default export is not declared in imported module 說明three.js沒有默認(rèn)的導(dǎo)出對(duì)象,應(yīng)該寫成 import * as three from 'three'; 或者可以這樣: import { Scene, WebGLRenderer, PerspectiveCamera, BoxGeometry, MeshBasicMaterial, Mesh} from 'three';

或者使用CommonJS的形式引入var three = require ('three');

2.用npm安裝軌道控制插件 npm install three-orbit-controls??

three-orbit-controls安裝地址:https://www.npmjs.com/package/three-orbit-controls

該插件引入之前確認(rèn)three.js 庫已經(jīng)引入, OrbitControls = require('three-orbit-controls')(THREE)

使用方法: controls = new OrbitControls(camera);

3.用npm安裝加載.obj和.mtl文件的插件 npm i –save three-obj-mtl-loader

three-obj-mtl-loader安裝地址 :https://www.npmjs.com/package/three-obj-mtl-loader

該插件引入之前必須確認(rèn)three.js庫已經(jīng)引入,該插件包括加載.obj和.mtl 文件的加載器

import {MTLLoader,OBJLoader} from 'three-obj-mtl-loader';

使用方法:mtlLoader = new MTLLoader(); objLoader = new OBJLoader();

注:?jiǎn)为?dú)使用three-mtl-loader 和 three-obj-loader兩個(gè)插件時(shí),會(huì)發(fā)生錯(cuò)誤:

初識(shí)three.js,搭建three.js+vue.js項(xiàng)目(threejs vue3)

4.用npm安裝three-css2drender插件, npm i –save three-css2drender

three-css2drender安裝地址: www.npmjs.com/package/three-css2drende

插件引入之前必須確認(rèn)htree.js庫已經(jīng)引入

import {CSS2DRenderer,CSS2DObject} from 'three-css2drenderer';

使用方法:

labelRenderer = new CSS2DRenderer();

label = new CSS2DObject( text );

作者:前端藏經(jīng)閣

轉(zhuǎn)發(fā)鏈接:https://www.yuque.com/xwifrr/uxqg5v/ggxx2b

相關(guān)新聞

聯(lián)系我們
聯(lián)系我們
公眾號(hào)
公眾號(hào)
在線咨詢
分享本頁
返回頂部