您好,登錄后才能下訂單哦!
這篇文章主要介紹了HTML5實(shí)現(xiàn)3D全景的示例,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
整個(gè)3D全景所用的相關(guān)理論就不多說(shuō)了,就稍微講一下本案例用到的相關(guān)理論
相信程序猿們會(huì)更加關(guān)注代碼實(shí)現(xiàn)的內(nèi)容
這次講解的demo是用css3DRender來(lái)構(gòu)建一個(gè)正方體的全景場(chǎng)景
想象一下,我們需要做的就是構(gòu)建一個(gè)正方體的盒子
然后把鏡頭放在以下這個(gè)正方體盒子里
每個(gè)面都貼上我們場(chǎng)景的一個(gè)面,那么當(dāng)鏡頭轉(zhuǎn)動(dòng)時(shí)看到的就是置身其中的全景
詳細(xì)理論的東西以后再說(shuō),這次先跑起來(lái)一個(gè)簡(jiǎn)單的demo吧
本教學(xué)用到兩個(gè)庫(kù):
threeJS和基于它的CSS3DRender.js
代碼是從官網(wǎng)上樣例上扒下來(lái)做了一點(diǎn)調(diào)整。
<!DOCTYPE html> <html> <head> <title>three.js css3d - panorama</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <style> body { background-color: #000000; margin: 0; cursor: move; overflow: hidden; } .surface { width: 1026px; height: 1026px; background-size: cover; position: absolute; } .surface .bg { position: absolute; width: 1026px; height: 1026px; } </style> </head> <body> <p> <p id="surface_0" class="surface"> <img class="bg" src="images/posx.jpg" alt=""> </p> <p id="surface_1" class="surface"> <img class="bg" src="images/negx.jpg" alt=""> </p> <p id="surface_2" class="surface"> <img class="bg" src="images/posy.jpg" alt=""> </p> <p id="surface_3" class="surface"> <img class="bg" src="images/negy.jpg" alt=""> </p> <p id="surface_4" class="surface"> <img class="bg" src="images/posz.jpg" alt=""> </p> <p id="surface_5" class="surface"> <img class="bg" src="images/negz.jpg" alt=""> </p> </p> <script src="js/three.min.js"></script> <script src="js/CSS3DRenderer.min.js"></script> <script src="js/index.js"></script> </body> </html>
html這邊沒(méi)什么特別的,首先把每個(gè)面放進(jìn)去,用p把每個(gè)面的圖片放進(jìn)去。
沒(méi)有用官網(wǎng)demo的實(shí)現(xiàn)方式是因?yàn)楣倬W(wǎng)是create一個(gè)img插入到頁(yè)面,我們?cè)趯?duì)每個(gè)面添加元素的時(shí)候不太方便
先把六個(gè)面定義好,如果要在每個(gè)面上加入一些交互的元素,直接在html上添加dom就可以了
一共就引入了3個(gè)js,除了index另外兩個(gè)都是壓縮過(guò)的js,不用關(guān)心,看一下index.js的實(shí)現(xiàn)
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 ); scene = new THREE.Scene();
那么很明顯這兩行代碼,字面上的意思就是創(chuàng)建了一個(gè)相機(jī),創(chuàng)建了一個(gè)場(chǎng)景。
那這里稍微解釋一下這兩個(gè)類(lèi)
以下是官網(wǎng)的解釋
大概意思:
這是一個(gè)模仿人眼的投影模式,它是用于渲染3D場(chǎng)景最常見(jiàn)的投影模式。
總之這個(gè)類(lèi)就是new一個(gè)鏡頭
下面是樣例代碼
這個(gè)類(lèi)的構(gòu)造函數(shù)接受四個(gè)參數(shù)
那么這四個(gè)參數(shù)具體是什么東西?
分別表示的
鏡頭夾角,寬高比,最近焦距,最遠(yuǎn)焦距
接下來(lái),用Scene類(lèi)創(chuàng)建場(chǎng)景
以下官方說(shuō)明
這東西創(chuàng)建了一個(gè)場(chǎng)景,這個(gè)場(chǎng)景允許你對(duì)某個(gè)東西某個(gè)位置通過(guò)threeJs渲染場(chǎng)景
創(chuàng)建了場(chǎng)景和相機(jī),我們需要往場(chǎng)景里面放入之前說(shuō)的正方體
首先定義好六個(gè)面的數(shù)據(jù),每個(gè)面的位置,3D旋轉(zhuǎn)的旋轉(zhuǎn)角度。
position三個(gè)參數(shù)分別對(duì)應(yīng)的x,y,z軸的位置
因?yàn)槲疫x的面寬度是1024px
所以位置是基于中心點(diǎn)的正負(fù)1024/2
rotation的三個(gè)參數(shù)分貝對(duì)應(yīng)xyz軸的旋轉(zhuǎn)角度
Math.PI/2代表90度
var sides = [ { position: [ -512, 0, 0 ],//位置 rotation: [ 0, Math.PI / 2, 0 ]//角度 }, { position: [ 512, 0, 0 ], rotation: [ 0, -Math.PI / 2, 0 ] }, { position: [ 0, 512, 0 ], rotation: [ Math.PI / 2, 0, Math.PI ] }, { position: [ 0, -512, 0 ], rotation: [ - Math.PI / 2, 0, Math.PI ] }, { position: [ 0, 0, 512 ], rotation: [ 0, Math.PI, 0 ] }, { position: [ 0, 0, -512 ], rotation: [ 0, 0, 0 ] } ]; /** * 根據(jù)六個(gè)面的信息,new出六個(gè)對(duì)象放入場(chǎng)景中 */ for ( var i = 0; i < sides.length; i ++ ) { var side = sides[ i ]; var element = document.getElementById("surface_"+i); element.width = 1026; // 2 pixels extra to close the gap.多余的2像素用于閉合正方體 var object = new THREE.CSS3DObject( element ); object.position.fromArray( side.position ); object.rotation.fromArray( side.rotation ); scene.add( object ); }
那么這里有一個(gè)新出現(xiàn)的類(lèi)CSS3DObject
不過(guò)這個(gè)類(lèi)不屬于官方類(lèi),而是我們引用的3DRender庫(kù)里的類(lèi)
沒(méi)有文檔我們看一下代碼
THREE.CSS3DObject = function (element) { THREE.Object3D.call(this); this.element = element; this.element.style.position = 'absolute'; this.addEventListener('removed', function (event) { if (this.element.parentNode !== null) { this.element.parentNode.removeChild(this.element); for (var i = 0, l = this.children.length; i < l; i++) { this.children[i].dispatchEvent(event) } } }) } ; THREE.CSS3DObject.prototype = Object.create(THREE.Object3D.prototype);
可以看出這是一個(gè)繼承于THREE.Object3D的類(lèi)
將傳入的element的postion改為絕對(duì)定位,然后加了個(gè)被移除時(shí)的事件。
沒(méi)有定義什么別的特別的東西,那么我們查一下官方Object3D的類(lèi)
這個(gè)類(lèi)就是一個(gè)定義對(duì)象的基本類(lèi),其中new的對(duì)象包含以下兩個(gè)屬性
.position The object's local position. .rotation Object's local rotation (see Euler angles), in radians.
分別表示對(duì)象的位置和旋轉(zhuǎn)角度。
那么for循環(huán)就是定義六個(gè)對(duì)象加入場(chǎng)景中
好,我們繼續(xù)
renderer = new THREE.CSS3DRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement );
這是我們引用的庫(kù)里的類(lèi)
這個(gè)類(lèi)的主要功能是根據(jù)three中的場(chǎng)景和鏡頭的相關(guān)信息
使用dom元素和css3D的屬性來(lái)渲染出來(lái)
在這里只是new了這個(gè)類(lèi)和設(shè)置了寬高
但是CSS3DRender在這里還沒(méi)有開(kāi)始渲染頁(yè)面
document.addEventListener( 'mousedown', onDocumentMouseDown, false ); document.addEventListener( 'wheel', onDocumentMouseWheel, false ); document.addEventListener( 'touchstart', onDocumentTouchStart, false ); document.addEventListener( 'touchmove', onDocumentTouchMove, false ); window.addEventListener( 'resize', onWindowResize, false );
這里的事件綁定就不詳細(xì)說(shuō)了
接下來(lái)解析一下渲染時(shí)的代碼
animate();
function animate() { requestAnimationFrame( animate ); // lat += 0.1; lat = Math.max( - 85, Math.min( 85, lat ) ); phi = THREE.Math.degToRad( 90 - lat ); theta = THREE.Math.degToRad( lon ); target.x = Math.sin( phi ) * Math.cos( theta ); target.y = Math.cos( phi ); target.z = Math.sin( phi ) * Math.sin( theta ); camera.lookAt( target ); /** * 通過(guò)傳入的scene和camera * 獲取其中object在創(chuàng)建時(shí)候傳入的element信息 * 以及后面定義的包括位置,角度等信息 * 根據(jù)場(chǎng)景中的obj創(chuàng)建dom元素 * 插入render本身自己創(chuàng)建的場(chǎng)景p中 * 達(dá)到渲染場(chǎng)景的效果 */ renderer.render( scene, camera ); }
requestAnimationFrame( animate );
這個(gè)方法可以根據(jù)幀速率觸發(fā)animate方法。
lat = Math.max( - 85, Math.min( 85, lat ) ); phi = THREE.Math.degToRad( 90 - lat ); theta = THREE.Math.degToRad( lon ); target.x = Math.sin( phi ) * Math.cos( theta ); target.y = Math.cos( phi ); target.z = Math.sin( phi ) * Math.sin( theta ); camera.lookAt( target );
這段代碼根據(jù)現(xiàn)成的(通過(guò)手指滑動(dòng)或鼠標(biāo)滑動(dòng)實(shí)時(shí)更新的)屬性值,調(diào)整camera鏡頭的位置
renderer.render( scene, camera );
然后渲染........
因?yàn)閞ender里面的代碼比較多,這里就不貼代碼了,大概總結(jié)一下render做的事情就是
首先render自己創(chuàng)建一個(gè)作為場(chǎng)景的p
通過(guò)傳入的scene和camera
獲取其中object在創(chuàng)建時(shí)候傳入的element信息
以及后面定義的包括位置,角度等信息
根據(jù)場(chǎng)景中的obj創(chuàng)建dom元素(就是通過(guò)dom實(shí)現(xiàn)本應(yīng)在canvas里的東西)
插入render本身自己創(chuàng)建的場(chǎng)景p中
當(dāng)鏡頭方向變了,獲取到的參數(shù)就變了,通過(guò)傳入的對(duì)象身上帶有的變化的參數(shù)改變頁(yè)面上dom元素的位置。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“HTML5實(shí)現(xiàn)3D全景的示例”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。