如何從入門Three.js到做出3D地球的示例分析,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
企業(yè)建站必須是能夠以充分展現(xiàn)企業(yè)形象為主要目的,是企業(yè)文化與產(chǎn)品對(duì)外擴(kuò)展宣傳的重要窗口,一個(gè)合格的網(wǎng)站不僅僅能為公司帶來巨大的互聯(lián)網(wǎng)上的收集和信息發(fā)布平臺(tái),成都創(chuàng)新互聯(lián)面向各種領(lǐng)域:茶樓設(shè)計(jì)等成都網(wǎng)站設(shè)計(jì)、全網(wǎng)營(yíng)銷推廣解決方案、網(wǎng)站設(shè)計(jì)等建站排名服務(wù)。
如果你沒接觸過3d可視化技術(shù), 你也許會(huì)認(rèn)為可視化非常難, 光是一個(gè)物體的陰影要如何計(jì)算就相當(dāng)復(fù)雜, 但是告訴你個(gè)好消息, 陰影的計(jì)算都是集成好的, 而我們只要設(shè)置好光源的位置,繪制好物體就可以了, 真的沒有想象中那么復(fù)雜, 本文面向有前端基礎(chǔ),但零可視化基礎(chǔ)的同學(xué), 我會(huì)從最基礎(chǔ)的入門知識(shí)說起。
學(xué)習(xí)可視化方面的技術(shù)會(huì)讓我們對(duì)計(jì)算機(jī), 對(duì)前端技術(shù)有更深的理解, 還可以做出更多有趣味的東西來, 本文是我踩了好多坑后總結(jié)出來的, 我更清楚一個(gè)初入門的小白哪里不懂。
three.js是 webgl的第三方庫(kù), 它更適合不太復(fù)雜的可視化項(xiàng)目, 而我們要做的3d地球項(xiàng)目使用它來做會(huì)更簡(jiǎn)單, 所以選擇了它, 放心后面也會(huì)說webgl相關(guān)知識(shí) 。
當(dāng)前效果如下:
1. 自食其力:不管是在公司還是網(wǎng)上都有類似的庫(kù), 但是當(dāng)遇到bug或是缺少功能的情況時(shí)就會(huì)很麻煩, 例如我們公司的FGL庫(kù)(一個(gè)內(nèi)網(wǎng)繪制3d景象的技術(shù)), 它官網(wǎng)上的例子很多都是錯(cuò)的, 使用起來也是一堆問題, 比如無法精準(zhǔn)選擇某個(gè)國(guó)家, 點(diǎn)擊事件消融等bug。還比如說Echarts的地球, 它太注重真實(shí)感并且用起來有點(diǎn)卡, 以及交互做的不太好。
2. 直指核心:去年我通過看書、看文章、看視頻認(rèn)真的學(xué)習(xí)three.js, 并做出了3d地球這個(gè)項(xiàng)目, 而這個(gè)系列文章將會(huì)直指做出3d地圖的核心知識(shí), 盡量不隨意擴(kuò)散知識(shí)面。
3. 更好入門:網(wǎng)上的教學(xué)文章千篇一律, 點(diǎn)進(jìn)去閱讀完感覺其對(duì)于一個(gè)three.js零基礎(chǔ)的同學(xué)來說都不太好懂, 教學(xué)視頻里的知識(shí)點(diǎn)太廣泛, 事無巨細(xì)的羅列, 而這個(gè)系列文章將更突出繪制3d地球這個(gè)重點(diǎn)。
4. 同道中人:我學(xué)習(xí)three.js就是為了做出3d地球, 期間走了不少?gòu)澛? 被某些問題卡了很久, 所以我更懂一個(gè)剛?cè)腴T的人困惑的點(diǎn)在哪里。
5. 專注vue:市面上較少專門針對(duì)vue做到開箱即用的3d地球插件, 而我們就要編寫這樣一款產(chǎn)品。
6. 不斷學(xué)習(xí):編寫文章也是我提高自己能力的一種方法, 死磕每個(gè)知識(shí)點(diǎn)讓自己的理解更上一層樓。
入門three.js技術(shù)。
繪制出3d地球。
做成專門vue使用的庫(kù)。
后期也會(huì)介紹著色器的概念與基本的使用技巧。
會(huì)介紹少量webgl的相關(guān)用法, 并且會(huì)有部分?jǐn)?shù)學(xué)知識(shí)。
主線劇情: 圍繞著如何做出3d地球, 這部分在vue工程里面進(jìn)行。
支線任務(wù): 每個(gè)分散的知識(shí)點(diǎn), 可能與3d地球沒關(guān)系, 但是它能幫助我們更好的理解3d技術(shù), 而這些知識(shí)點(diǎn)我就不在vue項(xiàng)目里面演示了, 會(huì)單獨(dú)創(chuàng)建一個(gè)html文件來演示說明。
像繪制圖形這類技術(shù), 最基本的概念就坐標(biāo)系, 下圖是二維坐標(biāo)系, 我們的故事就從這個(gè)家伙開始。
我們用(0, 0)表示坐標(biāo)的中心點(diǎn), 繪制一條起點(diǎn)為中心點(diǎn)長(zhǎng)度為1的線段可以使用 (0, 0) (1, 0)這兩個(gè)點(diǎn)相連表示。
關(guān)于向量的概念后面需要用數(shù)學(xué)知識(shí)的時(shí)候再介紹, 前幾篇文章就越通俗越好。
在three.js中我們要打交道的就是下面這位三維坐標(biāo)系
他的坐標(biāo)原點(diǎn)就是(0, 0, 0), 繪制一條起點(diǎn)為中心點(diǎn)的長(zhǎng)度為1的線段可以是 (0, 0, 0) (1, 0, 0)。
這里要記住, three.js里面設(shè)置的默認(rèn)坐標(biāo)系就是這種形式x向右, y向上, z向前, 之所以說是默是因?yàn)樗梢孕薷摹?/p>
上圖中, 觀看這個(gè)三維坐標(biāo)系的目光其實(shí)是在斜上方, 正常情況下在我們開發(fā)的時(shí)候z軸是正對(duì)著我們的眼睛的, 所以你只能看到z軸是一個(gè)點(diǎn),
在開發(fā)與學(xué)習(xí)的時(shí)候, 最好先把坐標(biāo)系繪制到頁面上, 方便我們更好的繪制。
假設(shè)現(xiàn)在我們的正前方有一個(gè)三維坐標(biāo)系的全息投影, 那么此時(shí)你的眼睛就相當(dāng)于一架相機(jī), 你看到的 坐標(biāo)系景象取決于你站的位置。
在three.js中就有這樣一個(gè)對(duì)象, 他就是負(fù)責(zé)從哪個(gè)角度觀察我們繪制的3d世界, 也就是相機(jī)這個(gè)概念的由來。
相機(jī)分為兩種, 正投影相機(jī)和透視投影相機(jī), 正投影相機(jī)就是你站的多遠(yuǎn)你看到的物體的大小都不變, 透視投影相機(jī)就是物體會(huì)近大遠(yuǎn)小, 下面是張引用圖 (圖片來自網(wǎng)絡(luò))。
正投影相機(jī)可以用在工程制圖上, 或者可以做一些視覺欺騙小游戲。
本文主要目的是繪制3d地球所以主要使用透視投影相機(jī)
引入three.js, 可以把包下載到本地, 也可以直接獲取在cdn上的資源, 引入之后全局會(huì)出現(xiàn)THREE對(duì)象, 我們就可以開始編程之旅了。
一個(gè)普普通通的html空文件的script標(biāo)簽里面, 發(fā)生著這樣的故事: 讓我們逐句解析
我們之后繪制的3d物體都要放入這個(gè)空間里面, 你可以把它當(dāng)做一個(gè)鴻蒙空間神器, 里面有一個(gè)小世界, 而我們是掌控者(很中二)。
const scene = new THREE.Scene();
相機(jī)的概念上面講述過了, PerspectiveCamera這個(gè)類就是透視投影相機(jī), 我們來逐個(gè)攻破他參數(shù)的意思。
1. 35: 視角也就是我們左眼與右眼可以看到的橫向角度, 其越小物體則越大, 因?yàn)槟抗庾儶M窄會(huì)突出物體, 你可以做一個(gè)實(shí)驗(yàn), 聚精會(huì)神的盯著看一個(gè)物體, 你就會(huì)發(fā)現(xiàn)此時(shí)你左右兩邊本來靠余光可以看到的物體你現(xiàn)在看不清, 這個(gè)就是你的視角變小了, 變小視角還可以使目標(biāo)物體比例變大, 我們知道這些就夠理解這個(gè)數(shù)字了, 后期可以利用這個(gè)原理做一些令人驚訝的動(dòng)畫特效。
2. window.innerWidth / window.innerHeight: 縱橫比寬/高, 這里寬高不會(huì)去寫px這種單位, 坐標(biāo)系里面是一種抽象的長(zhǎng)度單位, 所以要告訴瀏覽器咱們當(dāng)前顯示圖像的區(qū)域的寬高比例(可以當(dāng)它是百分比布局, 就像我們寫css布局時(shí)使用vh vw為單位)。
3. 1: 近平面, 簡(jiǎn)單理解就是當(dāng)一個(gè)圖像距離相機(jī)的距離小于1的時(shí)候, 就不顯示這個(gè)圖像了。
4. 1000: 遠(yuǎn)平面, 簡(jiǎn)單理解就是當(dāng)一個(gè)圖像距離相機(jī)的距離大于1000的時(shí)候, 就不顯示這個(gè)圖像了。
5. camera.position.z = 10; 相機(jī)的坐標(biāo)不設(shè)置的話, 默認(rèn)就是(0, 0, 0)坐標(biāo)原點(diǎn), 這樣類似腦袋在坐標(biāo)軸原點(diǎn)上看坐標(biāo)軸, 所以這里要設(shè)置距離坐標(biāo)中心有一定距離, 也就是遠(yuǎn)距離觀察這個(gè)坐標(biāo)系。
const camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000); camera.position.z = 10;
無聊的知識(shí): 我們?cè)谕?d游戲的時(shí)候, 是不是有時(shí)候與另一個(gè)游戲人物距離太近了就會(huì)出現(xiàn)人物中空的效果, 這些很可能就是他的某些部分距離你相機(jī)的距離, 小于了近平面的距離導(dǎo)致的。
物體距離眼睛越近越大, 越遠(yuǎn)越小, 因?yàn)橐粋€(gè)物品無限大與無限遠(yuǎn)沒有意義, 顯示起來浪費(fèi)性能, 所以才會(huì)設(shè)置近平面與遠(yuǎn)平面。
WebGLRenderer生成一個(gè)渲染實(shí)例, 用來渲染我們所有的3d效果。
setSize設(shè)置場(chǎng)景的寬高。
setClearColor設(shè)置背景色, 這個(gè)背景色不是平面的, 是全方位的, 你可以想想成你在一個(gè)屋子里, 這個(gè)顏色就是屋子墻壁、地板、天花板的顏色(.5是透明度)。
renderer.domElement生成的渲染的實(shí)例, 這個(gè)要放到對(duì)應(yīng)的dom容器里面(是個(gè)canvas標(biāo)簽)。
const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearColor(0x00FFFF, .5) document.body.appendChild(renderer.domElement);
知識(shí)點(diǎn): setClearColor不寫就是黑色
知識(shí)點(diǎn): setClearColor可以直接寫"red"這種, 不用必須16進(jìn)制。
鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)
AxisHelper: 用于生成輔助坐標(biāo)實(shí)例, 2代表這個(gè)坐標(biāo)系的長(zhǎng)度, 因?yàn)槲覀儾灰欢ㄐ枰嚅L(zhǎng)的輔助線。
scene: 老朋友場(chǎng)景, 它的add方法就是把某某某加入到場(chǎng)景中來。
const axisHelper = new THREE.AxisHelper(2) scene.add(axisHelper)
1. 第一個(gè)參數(shù)是場(chǎng)景, 第二個(gè)參數(shù)是相機(jī)。
renderer.render(scene, camera);
下面是效果圖, z軸正對(duì)著我們所以看不到:
在斜上方看到是如下的效果, 之后的章節(jié)會(huì)說如何調(diào)整相機(jī)的位置與角度
完整的代碼如下:
不畫一個(gè)立方體感覺對(duì)不起 第一篇這個(gè)題目, 要注意了在three.js中你可以理解為繪制一個(gè)幾何體需要兩部分, 一個(gè)是幾何體本身, 比如這個(gè)幾何體的長(zhǎng)寬高, 另一個(gè)就是材質(zhì)可以簡(jiǎn)單理解為表面的顏色樣式。 geometry這個(gè)單詞我們會(huì)經(jīng)常打交道的, 來一起記下它吧。
BoxGeometry 長(zhǎng)方體
const geometry = new THREE.BoxGeometry(1, 2, 3);
1: '長(zhǎng)', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在x軸上的長(zhǎng)度。
2: '高', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在y軸上的長(zhǎng)度。
3: '寬', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在z軸上的長(zhǎng)度。
new出來的實(shí)例上面會(huì)有這個(gè)幾何體的點(diǎn)的信息, 面的信息等等, 這個(gè)后面再詳細(xì)說這次主要入門。
MeshBasicMaterial 材質(zhì)
顏色與上面設(shè)置setClearColor一樣, 什么寫法都行的, 下面是我設(shè)置了一個(gè)紅色的材質(zhì)。const material = new THREE.MeshBasicMaterial({ color: 'red' });
生成'網(wǎng)格' Mesh
const cube = new THREE.Mesh(geometry, material);網(wǎng)格上含有位置信息、旋轉(zhuǎn)信息、縮放信息等等, 他需要用幾何體與材質(zhì)兩個(gè)參數(shù), 但其實(shí)并不像網(wǎng)上說的必須要有材質(zhì), 不傳材質(zhì)也能顯示。
放入場(chǎng)景
也就是場(chǎng)景對(duì)象scene本身有個(gè)add方法。scene.add(cube);
右上方視角
放入場(chǎng)景的幾種方式
1: 我直接放入geometryscene.add(geometry); 會(huì)報(bào)錯(cuò)了, 可以理解為不是網(wǎng)格對(duì)象所以報(bào)錯(cuò)了。以后遇到這類報(bào)錯(cuò)一定要考慮類型問題。
2: 未設(shè)置材質(zhì)
const cube = new THREE.Mesh(geometry); scene.add(cube);
白白的一片, 并且控制臺(tái)沒有報(bào)錯(cuò)。
關(guān)于從入門Three.js到做出3D地球的示例分析問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。