three.js快速入門和實戰

若是對您有幫助,請必定幫忙點個star,讓我有更大的動力繼續分享,若是您要轉載,務必補上個人github地址,謝謝兄dei;但願在幫到您的同時,您能給我點個star或者follow就極好了
原發佈於我的github倉庫:https://github.com/screetBloom/whatsImagecss

理解ThreeJs(包括如何實現這個基礎的「地球」,擴展中..)

最下面添加了一個Xplan的實現
html

一、下載three.js, 並在頁面引用

若是你找不到合適的下載地址的話,能夠看看這個CDN,Here,若是想要下載的話,拷貝CDN地址直接URL打開網頁,複製原代碼.
官網看這裏;官網例子看這裏。
有一點須要注意,three.js版本不少,一樣的代碼可能會產生差別的效果,也可能由於代碼和js版本不一致而出不來效果。css3

二、概念

一個典型的Three.js程序至少要包括渲染器(Renderer)、場景(Scene)、照相機(Camera),以及咱們在場景中建立的物體(Cube).git

3.Do it(簡單入門,以我本身爲例)

前提是已經引入了three.js(能夠經過全局變量Three能夠訪問到內部屬性方法)
具體使用的時候,須要注意須要如下三點:引入three.js、聲明充當容器的canvas、在JavaScript代碼中定義一個init函數、加載init函數(init函數不須要必定在頁面加載完當即執行,綁定按鈕什麼的均可以)github

let us begin!canvas

HTML中定義:api

<body onload="init()">

<canvas id="mainCanvas" width="400px" height="300px" ></canvas>

</body>

在JavaScript代碼中定義一個init函數,聲明在HTML加載完後執行(讓DOM先加載):bash

function init() { 
   // ...  coding  here
}

通常建立的流程是在init函數裏框架

總體需求以下:ide

<!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
 </head>
 <body onload="init()">
 
 <canvas id="mainCanvas" width="1600px" height="1200px" ></canvas>
 
 <script>
     function init() {
         // ... three.js程序的4個構成部分
     }
 
 
 </script>
 
 </body>
 </html>
(1).聲明一個 渲染器,給個背景色

背景色能夠理解爲 幕布,這裏設置爲黑色

//定義  渲染器 renderer
var renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('mainCanvas') });

//背景色  黑色
renderer.setClearColor(0x000000);

有一個地方須要注意:這裏能夠將WebGL渲染器替換爲Canvas渲染器來達到更好的兼容性,可是它的精美度和性能不如WebGL渲染,並致使canvas以2D的方式渲染.

(2).定義場景

Scene能夠理解爲幕布裏面的一整幕,就是用戶看到的「世界」。接下來聲明的camera、cube(物體) 都要加到這個「世界」裏面去,隨着camera的移動呈現給用戶不一樣的畫面。

//定義  場景scene
var scene = new THREE.Scene();
(3).設置照相機(眼睛所處的位置), 必需要添加到場景中

能夠理解成咱們眼睛所在的位置,它的位置決定了咱們最終看到的是什麼,而Scene決定幕布裏有哪些東西。若是Camera位置不合理,即便Scene中有無數物體、相互之間有很是複雜的關係,咱們看到的可能永遠都是幕布(這裏是一片漆黑)。

有一點須要特別注意,座標系爲笛卡爾右手座標系,而不是咱們數學書上的空間直角座標系。可是,設置座標時依然是按照x、y、z的順序來的

另外照相機默認的觀察方向是指向z軸負方向(就是朝向屏幕),這裏採用的都是透視投影(近大遠小),正交(遠近同樣)能夠本身看一下;這裏採用透視是爲了觀測3D效果。二者差別看demo

設置照相機代碼以下:

//設置照相機,視角爲透視模型(角度,長寬比,最近距離,最遠距離)
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
//相機位置(x,y,z)
camera.position.set(0, 0, 5);
//添加到場景中
scene.add(camera);
(4).畫出物體 , 添加到場景中

這裏的CubeGeometry表示我要繪製的是立方體(因此給出了長寬高),MeshBasicMaterial表示「網格基礎材質」的材料,通俗的能夠理解爲給這個立方體一種外在的「皮膚」。

多種渲染類型可供選擇,詳情查詢官網Materials

//建立一個 x、y、z方向爲 一、二、3,顏色爲 紅色 的矩形
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
new THREE.MeshBasicMaterial({
        color: 0xff0000
        })
);
scene.add(cube);
(5).渲染,需傳入 場景和照相機
//渲染
renderer.render(scene, camera);

等學到後來的時候,能夠事先設置 着色精度、背景色透明、最大燈光數等等

(6).完整demo代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>理解基本的渲染器/場景/相機/物體</title>
    <!--<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>-->
    <!--<script src="https://cdn.bootcss.com/three.js/r83/three.js"></script>-->
    <script src="../js/three.js"></script>
</head>
<body onload="init()">

<canvas id="mainCanvas" width="400px" height="300px" ></canvas>

<script>
    function init() { // ...

        //定義  渲染器 renderer
        var renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('mainCanvas') });

        renderer.setClearColor(0x000000);   //背景色  黑色

        //定義  場景scene
        var scene = new THREE.Scene();

        //定義相機  camera
        var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
        camera.position.set(0, 0, 5);
        scene.add(camera);

        //建立一個 x、y、z方向爲 一、二、3,顏色爲 紅色
        var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
            new THREE.MeshBasicMaterial({
            color: 0xff0000
            })
        );
        scene.add(cube);

        //定義了場景中的物體,設置好的照相機以後,渲染
        renderer.render(scene, camera);

    }

</script>
</body>
</html>

效果如圖:
Alt text

(7).進一步理解camera(位置)
camera.position.set(0, 0, 5);

將position的z軸改成10

camera.position.set(0, 0, 10);

效果如圖:
Alt text

爲何會看起來明顯變小呢?
其實很簡單 ,用的是透視鏡頭(PerspectiveCamera),近大遠小,camera離物體的距離遠了,物體天然看起來就小了。(X、Y軸同理)

Alt text

(7).進一步理解camera(角度)
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
camera.position.set(0, 0, 5);

將角度大小改爲60度

var camera = new THREE.PerspectiveCamera(60, 4 / 3, 1, 1000);
camera.position.set(0, 0, 5);

效果如圖:
Alt text

此次不如上次明顯,可是仍是變小了,這是爲何呢?
雖然正方體的實際大小並未改變,camera的位置也沒變,可是將camera的豎直張角設置得更大時,視角變大了,於是正方體相對於整個視角的大小就變小了,看起來正方形就顯得變小了。

Alt text

4.正式開始(從基本立方體和球入手)

若是說概念的話,最最基本的入門概念到這裏就差很少了,接下來的貼圖,旋轉,動畫,導入等等都是這個概念框架上的理解(我學的也不深)
可是我就到這裏結束的話,你確定會說,ntm,老子用個css3,一個幕布黑色,一個紅色長方形,要你這麼多代碼嗎?threejs就這點做用的話,有什麼用?

其實,剛剛咱們的代碼就是一個長方體,還記得咱們設置的長寬高嗎,長方形怎麼會有三維呢!
實際上是由於camera就是咱們的眼睛,咱們被一個長方體的一個面給遮住了全部視野,它其實依然仍是一個立方體,只是如今咱們看不到而已,那麼,咱們就來看看這個立方體。

加上這句

//建立一個 x、y、z方向爲 一、二、3,顏色爲 紅色
        var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
            new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: true     //這裏這句,要加
            })
        );
        scene.add(cube);

這句話的意思是說,只用把邊的顏色塗一下就能夠了,不要塗整個面.

Alt text

若是你有圖形圖像的基礎的話,應該已經看出來了。由於在前面咱們選的是透視投影的camera,因此這個就是長方體的透視圖,只是不夠明顯而已。

那麼如今咱們再來好好看看,明確的讓你們看出來它是一個長方體。

首先,給長方體進行多重的面切割(這樣是爲了在不對6個面進行塗色的狀況下,好看出來它的輪廓)
由本來的定義長方體,加一句:

從本來的這樣:

//建立一個 x、y、z方向爲 一、二、3,顏色爲 紅色
        var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
            new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: true     //這裏這句,要加
            })
        );
        scene.add(cube);

變成這樣:

//建立一個 x、y、z方向爲 一、二、3,顏色爲 紅色
        var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3,20,20,30),   
        //後面加上了 20,20,30,x軸的兩面都切割20份,y軸的兩面都切割20份,z軸的兩面都切割成30份
            new THREE.MeshBasicMaterial({
                color: 0xff0000,
                wireframe: true
            })
        );
        scene.add(cube);

效果圖:
Alt text

如今大體上能夠看出來立方體的結構了,那咱們如今再進一步,將立方體旋轉過來看,直接驗證是否是。
在定義相機這裏,改變咱們camera的位置,來達到旋轉立方體的效果.

//定義相機  camera
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
camera.position.set(-2, -4, 5);
scene.add(camera);

可是單純這樣的話,你會發現如今整個立方體看不到了。由於咱們位置移動了,camera移動走了,可是沒有注視着立方體,至關於:

Alt text

變成了:

Alt text

天然就看不到了。因此加上這句:

camera.lookAt(new THREE.Vector3(0, 0, 0));

意思就是。眼睛雖然移動了,可是還要看着原點,也就是物體繪製的地方。
效果以下:

Alt text

所有代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>理解基本的渲染器/場景/相機/物體</title>
    <script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
</head>
<body onload="init()">



<canvas id="mainCanvas" width="1600px" height="1200px" ></canvas>


<script>
    function init() { // ...

        //定義  渲染器 renderer
        var renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('mainCanvas') });

        renderer.setClearColor(0x000000);   //背景色  黑色

        //定義  場景scene
        var scene = new THREE.Scene();

        //定義相機  camera
        var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
        camera.position.set(-2, -4, 5);
        scene.add(camera);

        //建立一個 x、y、z方向爲 一、二、3,顏色爲 紅色
        var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3,20,20,30),
            new THREE.MeshBasicMaterial({
                color: 0xff0000,
                wireframe: true
            })
        );
        scene.add(cube);

        camera.lookAt(new THREE.Vector3(0, 0, 0));

        //定義了場景中的物體,設置好的照相機以後,渲染
        renderer.render(scene, camera);

    }

</script>
</body>
</html>

球(爲開始的那個旋轉的地球作準備)

其實和立方體沒有什麼區別,都是調用three.js,告訴這個庫我要繪製一個球體.

繪製長方體是這樣的:

//建立一個 x、y、z方向爲 一、二、3,顏色爲 紅色
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
    new THREE.MeshBasicMaterial({
        color: 0xff0000,
        wireframe: true
        })
);
scene.add(cube);

繪製球體其實就是這樣的:

//添加球體 ,  紅色   這裏的三個參數是(半徑、經度上的切片數,緯度上的切片數)。經緯度數據越大圓越是精細(共7個參數)
var cube = new THREE.Mesh(
    new THREE.SphereGeometry(3, 18, 12),
        new THREE.MeshBasicMaterial({
            color: 0xff0000,
            wireframe: true
        })
);
scene.add(cube);

效果圖:

Alt text

5.加點特效rotation(其餘的,像位置和縮放的特效後續一直會寫)

咱們這裏的特效,目前就指旋轉,思路也很簡單,每間隔一段時間,讓這個球體按y軸(x、z軸也均可以)旋轉一點,而後每隔一段時間從新渲染(不能渲染的太慢).

旋轉函數也很簡單:

function draw() {
        cube.rotation.y = (cube.rotation.y + 0.01) % (Math.PI * 2);
        renderer.render(scene, camera);
    }

渲染寫好了,就缺一個時間間隔了.這裏用setInterval,主要是寫demo的時候好控制時間看看具體的運行狀況,
效果如圖:

Alt text

接下來其實就是渲染圖片了。
原圖如圖:
Alt text

渲染(貼圖)其實就是一句代碼:

//添加物體 ,正方體  用圖片圖片進行渲染
cube = new THREE.Mesh(
    new THREE.SphereGeometry(3, 20, 30),
        new THREE.MeshBasicMaterial({
                //用這個圖片來渲染物體
                map:THREE.ImageUtils.loadTexture('../../img/map.jpg'),
        })
);
scene.add(cube);

Alt text

所有代碼以下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>旋轉_球體</title>
    <script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
</head>
<body onload="init()">
<canvas id="mainCanvas" width="1600px" height="1200px" ></canvas>

<script>
    var cube=null;
    var renderer=null;
    var scene=null;
    var camera=null;
    function init() { // ...

        //定義  渲染器 renderer
        renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('mainCanvas') });

        renderer.setClearColor(0x000000);   //背景色  黑色

        //定義  場景scene
        scene = new THREE.Scene();

        //設置照相機
        camera = new THREE.PerspectiveCamera(45, 400 / 300, 1, 1000);
        camera.position.set(0, 0, 9);
        scene.add(camera);

        //添加物體 ,正方體  用圖片圖片進行渲染
        cube = new THREE.Mesh(
            new THREE.SphereGeometry(3, 20, 30),
            new THREE.MeshBasicMaterial({
                //用這個圖片來渲染物體
                map:THREE.ImageUtils.loadTexture('../../img/map.jpg'),
            })
        );
        scene.add(cube);

//        camera.lookAt(new THREE.Vector3(0, 0, 0));

        //定義了場景中的物體,設置好的照相機以後,渲染
        setInterval(draw, 20);

    }

    function draw() {
        cube.rotation.y = (cube.rotation.y + 0.01) % (Math.PI * 2);
        renderer.render(scene, camera);
    }


</script>
</body>
</html>

PS. 若是你須要渲染的圖片素材的話,點這裏

6.鋪設場景(多物體的相互關係)

<video width="100%" height="100%" controls="controls" poster="http://7xl4c6.com1.z0.glb.clo...;>

<source src="http://7xl4c6.com1.z0.glb.clouddn.com/FrWRH9jKm109uFR3k7th0yuPQwhn" />

</video>

有空進一步拓展 ,最終可能會演變成一個宇宙

先貼出這部分的源代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>three.js進行場景佈置</title>
    <script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
</head>
<body onload="init()">
<canvas id="mainCanvas" ></canvas>
<script>

    var sphere,
        scene,
        camera,
        renderer;

    function init() { // ...
        var winWidth = window.innerWidth,
            winHeight = window.innerHeight,
            mainCanvas = document.getElementById('mainCanvas');
        mainCanvas.width = winWidth;
        mainCanvas.height = winHeight;
        //定義  渲染器 renderer
        renderer = new THREE.WebGLRenderer({ canvas: mainCanvas });

        renderer.setClearColor(0x000000);   //背景色  黑色

        //定義  場景scene
        scene = new THREE.Scene();

        //定義相機  camera
        camera = new THREE.PerspectiveCamera(45, winWidth / winHeight, 1, 1000);
        camera.position.set(0, 70, 300);
        scene.add(camera);

        //建立一個 平面
        var plane = new THREE.Mesh(new THREE.PlaneGeometry(500, 500,100,100),
            new THREE.MeshBasicMaterial({
                color: 0xff0000,
                wireframe: true
            })
        );
        plane.rotation.x = Math.PI / 2;
        plane.position.z = 100;

        //建立一個 球 ,並進行渲染
        sphere = new THREE.Mesh(
            new THREE.SphereGeometry(30, 18,18),
            new THREE.MeshBasicMaterial({
                map:THREE.ImageUtils.loadTexture('../../img/map.jpg'),
            })
        );
        sphere.position.y=30;
        sphere.position.z=150;

        //建立一個 立方體
        var cube = new THREE.Mesh(new THREE.CubeGeometry(50, 50,50,10,10),
            new THREE.MeshBasicMaterial({
                color: 0xffff33,
                wireframe: true
            })
        );
        cube.position.x = 100;
        cube.position.z = 50;

        //添加物體
        scene.add(plane);
        scene.add(sphere);
        scene.add(cube);

        camera.lookAt(new THREE.Vector3(0, 0, 0));

        //定義了場景中的物體,設置好的照相機以後,渲染
        setInterval(draw, 20);
    }

    function draw() {
        sphere.rotation.y = (sphere.rotation.y + 0.01) % (Math.PI * 2);
        renderer.render(scene, camera);
    }
</script>
</body>
</html>

Aframe試玩(基於720yun)

http://720yun.com/t/767jzzkurn4

Alt text

Xpaln的實現

http://7xl4c6.com1.z0.glb.clouddn.com/FgOz6YOkVlaF8AiNNqpMml-fNmX0

Xplan基本是抄"jackyang"實現的(人家提供思路,本身實現仍是須要花點時間的)

結尾

除了本身設計模型,具體到項目還須要設計人員製做複雜3d模型,咱們導入到Three程序中,這部分能夠本身搜索,這裏只作簡單的入門介紹。
我的實現的時候能夠本身搜索Three.js框架(Aframe、krpano等)。感興趣又不想花太多時間的同窗能夠搜一下「720yun」

這裏只是簡要介紹我所瞭解的一部分,你們詳情能夠關注 Ovilia(張雯莉)的github:https://github.com/Ovilia/Thr... ,包括本次分享最開始的概念部分有些也是使用她的demo改的(私信徵求過贊成)。

相關文章
相關標籤/搜索