首頁  >  文章  >  web前端  >  HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)

HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)

黄舟
黄舟原創
2018-05-18 10:29:0536951瀏覽

前言

在現在市面上很多全景H5的環境下,要實現全景的方式有很多,可以用css3直接構建也可以用基於threeJs的庫來實現,還有很多別的製作全景的軟體使用
本教學適用於未開發過3D全景的工程獅子

如果覺得內容太無聊可以直接跳到最後

下載代碼

#理論

整個3D全景所用的相關理論就不多說了,就稍微講一下本案例用到的相關理論

相信程式猿們會更關注程式碼實現的內容

這次講解的demo是用css3DRender來構建一個立方體的全景場景

想像一下,我們需要做的就是構建一個正方體的盒子

然後把鏡頭放在以下這個正方體盒子裡

每個面都貼上我們場景的一個面,那麼當鏡頭轉動時看到的就是置身其中的全景
HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)

詳細理論的東西以後再說,這次先跑起來一個簡單的demo吧

demo解析

本教學用到兩個函式庫:
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>
<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這邊沒什麼特別的,先把每個面放進去,用p把每個面的圖片放進去。

沒有用官網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();

那麼很明顯這兩行程式碼,字面上的意思就是創建了一個相機,創建了一個場景。

那這裡稍微解釋一下這兩個類別

PerspectiveCamera

以下是官網的解釋
HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)
大概意思:
這是模仿人眼的投影模式,它是用來渲染3D場景最常見的投影模式。
總之這個類別就是new一個鏡頭
下面是範例程式碼
HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)

這個類別的建構子接受四個參數
HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)

那麼這四個參數具體是什麼東西?
HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)

分別表示的
鏡頭夾角,寬高比,最近焦距,最遠焦距

Scene

接下來,用Scene類別創建場景
以下官方說明
HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)

這東西創建了一個場景,這個場景允許你對某個東西某個位置透過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

那麼這裡有一個新出現的類別CSS3DObject
不過這個類別不屬於官方類,而是我們引用的3DRender庫裡的類

沒有文檔我們看一下代碼

THREE.CSS3DObject = function (element) {
    THREE.Object3D.call(this);
    this.element = element;
    this.element.style.position = &#39;absolute&#39;;
    this.addEventListener(&#39;removed&#39;, 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的類別

Object3D

HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)
這個類別就是一個定義物件的基本類,其中new的物件包含以下兩個屬性

.position

The object&#39;s local position.

.rotation

Object&#39;s local rotation (see Euler angles), in radians.

分別表示物件的位置和旋轉角度。
那麼for迴圈就是定義六個物件加入場景中
好,我們繼續

renderer = new THREE.CSS3DRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

CSS3DRenderer

這是我們引用的庫裡的類別
這個類別的主要功能是根據three中的場景和鏡頭的相關資訊
使用dom元素和css3D的屬性來渲染出來

在這裡只是new了這個類別和設定了寬高
但是CSS3DRender在這裡還沒開始渲染頁面

document.addEventListener( &#39;mousedown&#39;, onDocumentMouseDown, false );
document.addEventListener( &#39;wheel&#39;, onDocumentMouseWheel, false );

document.addEventListener( &#39;touchstart&#39;, onDocumentTouchStart, false );
document.addEventListener( &#39;touchmove&#39;, onDocumentTouchMove, false );

window.addEventListener( &#39;resize&#39;, 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本身自己创建的场景p中
     * 达到渲染场景的效果
     */
    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自己创建一个作为场景的p

通过传入的scene和camera

获取其中object在创建时候传入的element信息
以及后面定义的包括位置,角度等信息

根据场景中的obj创建dom元素(就是通过dom实现本应在canvas里的东西)

插入render本身自己创建的场景p中

当镜头方向变了,获取到的参数就变了,通过传入的对象身上带有的变化的参数改变页面上dom元素的位置。

达到渲染场景的效果

以上是HTML5開發實例-3D全景(ThreeJs全景Demo) 詳解(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn