在如今市面上不少全景H5的環境下,要實現全景的方式有不少,能夠用css3直接構建也能夠用基於threeJs的庫來實現,還有不少別的製做全景的軟件使用
本教學適用於未開發過3D全景的工程獅css
若是以爲內容太無聊能夠直接跳到最後html
下載代碼css3
整個3D全景所用的相關理論就很少說了,就稍微講一下本案例用到的相關理論canvas
相信程序猿們會更加關注代碼實現的內容app
此次講解的demo是用css3DRender來構建一個正方體的全景場景dom
想象一下,咱們須要作的就是構建一個正方體的盒子ide
而後把鏡頭放在如下這個正方體盒子裏函數
每一個面都貼上咱們場景的一個面,那麼當鏡頭轉動時看到的就是置身其中的全景
post
詳細理論的東西之後再說,此次先跑起來一個簡單的demo吧this
本教學用到兩個庫:
threeJS和基於它的CSS3DRender.js
代碼是從官網上樣例上扒下來作了一點調整。
<!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> <div> <div id="surface_0" class="surface"> <img class="bg" src="images/posx.jpg" alt=""> </div> <div id="surface_1" class="surface"> <img class="bg" src="images/negx.jpg" alt=""> </div> <div id="surface_2" class="surface"> <img class="bg" src="images/posy.jpg" alt=""> </div> <div id="surface_3" class="surface"> <img class="bg" src="images/negy.jpg" alt=""> </div> <div id="surface_4" class="surface"> <img class="bg" src="images/posz.jpg" alt=""> </div> <div id="surface_5" class="surface"> <img class="bg" src="images/negz.jpg" alt=""> </div> </div> <script src="js/three.min.js"></script> <script src="js/CSS3DRenderer.min.js"></script> <script src="js/index.js"></script> </body> </html>
html這邊沒什麼特別的,首先把每一個面放進去,用div把每一個面的圖片放進去。
沒有用官網demo的實現方式是由於官網是create一個img插入到頁面,咱們在對每一個面添加元素的時候不太方便
先把六個面定義好,若是要在每一個面上加入一些交互的元素,直接在html上添加dom就能夠了
一共就引入了3個js,除了index另外兩個都是壓縮過的js,不用關心,看一下index.js的實現
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 ); scene = new THREE.Scene();
那麼很明顯這兩行代碼,字面上的意思就是建立了一個相機,建立了一個場景。
那這裏稍微解釋一下這兩個類
如下是官網的解釋
大概意思:
這是一個模仿人眼的投影模式,它是用於渲染3D場景最多見的投影模式。
總之這個類就是new一個鏡頭
下面是樣例代碼
這個類的構造函數接受四個參數
那麼這四個參數具體是什麼東西?
圖片來源:https://isux.tencent.com/3d.html
分別表示的
鏡頭夾角,寬高比,最近焦距,最遠焦距
接下來,用Scene類建立場景
如下官方說明
這東西建立了一個場景,這個場景容許你對某個東西某個位置經過threeJs渲染場景
建立了場景和相機,咱們須要往場景裏面放入以前說的正方體
首先定義好六個面的數據,每一個面的位置,3D旋轉的旋轉角度。
position三個參數分別對應的x,y,z軸的位置
由於我選的面寬度是1024px
因此位置是基於中心點的正負1024/2
rotation的三個參數分貝對應xyz軸的旋轉角度
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 ] } ]; /** * 根據六個面的信息,new出六個對象放入場景中 */ 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 ); }
那麼這裏有一個新出現的類CSS3DObject
不過這個類不屬於官方類,而是咱們引用的3DRender庫裏的類
沒有文檔咱們看一下代碼
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);
能夠看出這是一個繼承於THREE.Object3D的類
將傳入的element的postion改成絕對定位,而後加了個被移除時的事件。
沒有定義什麼別的特別的東西,那麼咱們查一下官方Object3D的類
這個類就是一個定義對象的基本類,其中new的對象包含如下兩個屬性
.position The object's local position. .rotation Object's local rotation (see Euler angles), in radians.
分別表示對象的位置和旋轉角度。
那麼for循環就是定義六個對象加入場景中
好,咱們繼續
renderer = new THREE.CSS3DRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement );
這是咱們引用的庫裏的類
這個類的主要功能是根據three中的場景和鏡頭的相關信息
使用dom元素和css3D的屬性來渲染出來
在這裏只是new了這個類和設置了寬高
可是CSS3DRender在這裏尚未開始渲染頁面
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 );
這裏的事件綁定就不詳細說了
接下來解析一下渲染時的代碼
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 ); /** * 經過傳入的scene和camera * 獲取其中object在建立時候傳入的element信息 * 以及後面定義的包括位置,角度等信息 * 根據場景中的obj建立dom元素 * 插入render自己本身建立的場景div中 * 達到渲染場景的效果 */ renderer.render( scene, camera ); }
requestAnimationFrame( animate );
這個方法能夠根據幀速率觸發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 );
這段代碼根據現成的(經過手指滑動或鼠標滑動實時更新的)屬性值,調整camera鏡頭的位置
renderer.render( scene, camera );
而後渲染........
由於render裏面的代碼比較多,這裏就不貼代碼了,大概總結一下render作的事情就是
首先render本身建立一個做爲場景的div
經過傳入的scene和camera
獲取其中object在建立時候傳入的element信息
以及後面定義的包括位置,角度等信息
根據場景中的obj建立dom元素(就是經過dom實現本應在canvas裏的東西)
插入render自己本身建立的場景div中
當鏡頭方向變了,獲取到的參數就變了,經過傳入的對象身上帶有的變化的參數改變頁面上dom元素的位置。
達到渲染場景的效果
連接: http://pan.baidu.com/s/1eR2Rlb8 密碼: sdyt