十分鐘快速實(shí)戰(zhàn)Three.js

前言

本文不會(huì)對(duì)Three.js幾何體、材質(zhì)、相機(jī)、模型、光源等概念詳細(xì)講解,會(huì)首先分成幾個(gè)模塊給大家快速演示一盒小案例。大家可以根據(jù)這幾個(gè)模塊快速了解Three.js的無(wú)限魅力。
學(xué)習(xí)

我們會(huì)使用Three.js簡(jiǎn)單做一個(gè)立方體,為了大家更能宏觀的了解Three.js。我將會(huì)分解成代碼段(模塊)來(lái)進(jìn)行開發(fā)。
模塊如下:

    場(chǎng)景對(duì)象
    網(wǎng)格模型
    光源
    相機(jī)
    渲染器對(duì)象
    渲染操作

1. 創(chuàng)建html文件

首先,我們得創(chuàng)建一個(gè)html文件,這樣才有地方開發(fā)。創(chuàng)建完成后,我們可以引入Three.js文件,今天,它可是主角。我是直接引入遠(yuǎn)程URL地址進(jìn)行加載,你也可以去官網(wǎng)進(jìn)行下載到本地引入。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
 
  </body>
</html>



2. 創(chuàng)建場(chǎng)景對(duì)象

借助Three.js引擎創(chuàng)建好一個(gè)虛擬的三維場(chǎng)景。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
  <script>  
      /*
       * 創(chuàng)建場(chǎng)景對(duì)象Scene
       */
      var scene = new THREE.Scene();
    </script>
  </body>
</html>



3. 創(chuàng)建網(wǎng)格模型

這行代碼new THREE.BoxGeometry(200, 200, 200)的意思是創(chuàng)建了一個(gè)長(zhǎng)200、寬200、高200的立方體對(duì)象。然后并通過(guò)代碼new THREE.MeshLambertMaterial給立方體對(duì)象定義材質(zhì),這里可以理解成立方體的屬性(包含了顏色、透明度等屬性),這里暫時(shí)列舉顏色屬性。然后我們需要將立方體與屬性聯(lián)系起來(lái),就用到網(wǎng)格模型,將兩者作為構(gòu)造函數(shù)Mesh的兩個(gè)參數(shù)傳進(jìn)去,最后添加到場(chǎng)景里面。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
  <script>  
      /*
       * 創(chuàng)建場(chǎng)景對(duì)象
       */
      var scene = new THREE.Scene();
      /*
       * 創(chuàng)建網(wǎng)格模型
       */
      var geometry = new THREE.BoxGeometry(200, 200, 200); //創(chuàng)建一個(gè)立方體幾何對(duì)象Geometry
      var material = new THREE.MeshLambertMaterial({
        color: '#f4f4f4',
      }); //材質(zhì)對(duì)象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對(duì)象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場(chǎng)景中
    </script>
  </body>
</html>



4. 設(shè)置光源

代碼new THREE.PointLight('#fff')創(chuàng)建了一個(gè)點(diǎn)光源對(duì)象,參數(shù)#fff定義的是光照強(qiáng)度, 你可以嘗試把參數(shù)更改為#666,你會(huì)看到立方體的表面顏色變暗,這很好理解,實(shí)際生活中燈光強(qiáng)度變低了,周圍的景物自然暗淡。比如夜空中的照明彈就是一個(gè)點(diǎn)光源例子。代碼THREE.AmbientLight('#333')創(chuàng)建了一個(gè)環(huán)境光對(duì)象,環(huán)境光的顏色會(huì)影響到整個(gè)場(chǎng)景,環(huán)境光沒有特定的光源,是模擬漫反射的一種光源,因此不需要指定位置它能將燈光均勻地照射在場(chǎng)景中每個(gè)物體上面,一般情況下用來(lái)弱化陰影或者添加一些顏色到環(huán)境中,因此不能將環(huán)境光作為場(chǎng)景中的唯一光源。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
  <script>  
      /*
       * 創(chuàng)建場(chǎng)景對(duì)象
       */
      var scene = new THREE.Scene();
      /*
       * 創(chuàng)建網(wǎng)格模型
       */
      var geometry = new THREE.BoxGeometry(200, 200, 200); //創(chuàng)建一個(gè)立方體幾何對(duì)象Geometry
      var material = new THREE.MeshLambertMaterial({
        color: '#f4f4f4',
      }); //材質(zhì)對(duì)象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對(duì)象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場(chǎng)景中
      /*
       * 設(shè)置光源
       */
      var point = new THREE.PointLight('#fff'); //點(diǎn)光源
      point.position.set(300, 100, 200); //點(diǎn)光源位置
      scene.add(point); //點(diǎn)光源添加到場(chǎng)景中
      
      var ambient = new THREE.AmbientLight('#333');//環(huán)境光
      scene.add(ambient); //環(huán)境光添加到場(chǎng)景中
    </script>
  </body>
</html>



5.設(shè)置相機(jī)

代碼new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000)創(chuàng)建了一個(gè)正射投影相機(jī)對(duì)象, 什么是“正射投影”,什么是“相機(jī)對(duì)象”, 比如把該構(gòu)造函數(shù)參數(shù)中用到的參數(shù)s,也就是代碼var s = 200中定義的一個(gè)系數(shù),可以把200更改為300,你會(huì)發(fā)現(xiàn)立方體顯示效果變小,這很好理解,相機(jī)構(gòu)造函數(shù)的的前四個(gè)參數(shù)定義的是拍照窗口大小, 就像平時(shí)拍照一樣,取景范圍為大,被拍的人相對(duì)背景自然變小了。camera.position.set(200, 300, 200);和camera.lookAt(scene.position)定義的是相機(jī)的位置和拍照方向,可以更改camera.position.set(200,300,200)參數(shù)重新定義的相機(jī)位置,把第一個(gè)參數(shù)也就是x坐標(biāo)從200更改為250, 你會(huì)發(fā)現(xiàn)立方的在屏幕上呈現(xiàn)的角度變了,這就像你生活中拍照人是同一個(gè)人,但是你拍照的位置角度不同,顯示的效果肯定不同。這些具體的參數(shù)細(xì)節(jié)可以不用管, 至少你知道相機(jī)可以縮放顯示三維場(chǎng)景、對(duì)三維場(chǎng)景的不同角度進(jìn)行取景顯示。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
  <script>  
      /*
       * 創(chuàng)建場(chǎng)景對(duì)象
       */
      var scene = new THREE.Scene();
      /*
       * 創(chuàng)建網(wǎng)格模型
       */
      var geometry = new THREE.BoxGeometry(200, 200, 200); //創(chuàng)建一個(gè)立方體幾何對(duì)象Geometry
      var material = new THREE.MeshLambertMaterial({
        color: '#f4f4f4',
      }); //材質(zhì)對(duì)象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對(duì)象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場(chǎng)景中
      /*
       * 設(shè)置光源
       */
      var point = new THREE.PointLight('#fff'); //點(diǎn)光源
      point.position.set(300, 100, 200); //點(diǎn)光源位置
      scene.add(point); //點(diǎn)光源添加到場(chǎng)景中
      var ambient = new THREE.AmbientLight('#333');//環(huán)境光
      scene.add(ambient); //環(huán)境光添加到場(chǎng)景中
      /*
       * 設(shè)置相機(jī)
       */
      var width = window.innerWidth; //窗口寬度
      var height = window.innerHeight; //窗口高度
      var k = width / height; //窗口寬高比
      var s = 200; //三維場(chǎng)景顯示范圍控制系數(shù),系數(shù)越大,顯示的范圍越大
      //創(chuàng)建相機(jī)對(duì)象
      var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(200, 300, 200); //設(shè)置相機(jī)位置
      camera.lookAt(scene.position); //設(shè)置相機(jī)方向(指向的場(chǎng)景對(duì)象)
    </script>
  </body>
</html>



6.創(chuàng)建渲染器對(duì)象

Three.js是基于原生WebGL封裝運(yùn)行的三維引擎。所以瀏覽器利用代碼new THREE.WebGLRenderer()就會(huì)渲染出一幀圖像??梢栽O(shè)置渲染區(qū)域尺寸和背景顏色。






<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
  <script>  
      /*
       * 創(chuàng)建場(chǎng)景對(duì)象
       */
      var scene = new THREE.Scene();
      /*
       * 創(chuàng)建網(wǎng)格模型
       */
      var geometry = new THREE.BoxGeometry(200, 200, 200); //創(chuàng)建一個(gè)立方體幾何對(duì)象Geometry
      var material = new THREE.MeshLambertMaterial({
        color: '#f4f4f4',
      }); //材質(zhì)對(duì)象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對(duì)象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場(chǎng)景中
      /*
       * 設(shè)置光源
       */
      var point = new THREE.PointLight('#fff'); //點(diǎn)光源
      point.position.set(300, 100, 200); //點(diǎn)光源位置
      scene.add(point); //點(diǎn)光源添加到場(chǎng)景中
      var ambient = new THREE.AmbientLight('#333');//環(huán)境光
      scene.add(ambient); //環(huán)境光添加到場(chǎng)景中
      /*
       * 設(shè)置相機(jī)
       */
      var width = window.innerWidth; //窗口寬度
      var height = window.innerHeight; //窗口高度
      var k = width / height; //窗口寬高比
      var s = 200; //三維場(chǎng)景顯示范圍控制系數(shù),系數(shù)越大,顯示的范圍越大
      //創(chuàng)建相機(jī)對(duì)象
      var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(200, 300, 200); //設(shè)置相機(jī)位置
      camera.lookAt(scene.position); //設(shè)置相機(jī)方向(指向的場(chǎng)景對(duì)象)
      /*
       * 創(chuàng)建渲染器對(duì)象
       */
      var renderer = new THREE.WebGLRenderer();
      renderer.setSize(width, height); //設(shè)置渲染區(qū)域尺寸
      renderer.setClearColor(0xb9d3ff, 1); //設(shè)置背景顏色
    </script>
  </body>
</html>



7.執(zhí)行渲染操作

將渲染好的區(qū)域指定場(chǎng)景、相機(jī)作為參數(shù),并且把區(qū)域添加到頁(yè)面上。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
  <script>  
      /*
       * 創(chuàng)建場(chǎng)景對(duì)象
       */
      var scene = new THREE.Scene();
      /*
       * 創(chuàng)建網(wǎng)格模型
       */
      var geometry = new THREE.BoxGeometry(200, 200, 200); //創(chuàng)建一個(gè)立方體幾何對(duì)象Geometry
      var material = new THREE.MeshLambertMaterial({
        color: '#f4f4f4',
      }); //材質(zhì)對(duì)象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對(duì)象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場(chǎng)景中
      /*
       * 設(shè)置光源
       */
      var point = new THREE.PointLight('#fff'); //點(diǎn)光源
      point.position.set(300, 100, 200); //點(diǎn)光源位置
      scene.add(point); //點(diǎn)光源添加到場(chǎng)景中
      var ambient = new THREE.AmbientLight('#333');//環(huán)境光
      scene.add(ambient); //環(huán)境光添加到場(chǎng)景中
      /*
       * 設(shè)置相機(jī)
       */
      var width = window.innerWidth; //窗口寬度
      var height = window.innerHeight; //窗口高度
      var k = width / height; //窗口寬高比
      var s = 200; //三維場(chǎng)景顯示范圍控制系數(shù),系數(shù)越大,顯示的范圍越大
      //創(chuàng)建相機(jī)對(duì)象
      var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(200, 300, 200); //設(shè)置相機(jī)位置
      camera.lookAt(scene.position); //設(shè)置相機(jī)方向(指向的場(chǎng)景對(duì)象)
      /*
       * 創(chuàng)建渲染器對(duì)象
       */
      var renderer = new THREE.WebGLRenderer();
      renderer.setSize(width, height); //設(shè)置渲染區(qū)域尺寸
      renderer.setClearColor(0xb9d3ff, 1); //設(shè)置背景顏色
      /*
       * 執(zhí)行渲染操作  
       */
      renderer.render(scene, camera); //指定場(chǎng)景、相機(jī)作為參數(shù)
      document.body.appendChild(renderer.domElement); //body元素中插入canvas對(duì)象
    </script>
  </body>
</html>



完整代碼

代碼body {margin: 0;overflow: hidden;}是為了隱藏body窗口區(qū)域滾動(dòng)條。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>three.js小案例</title>
    <style>
      body {
        margin: 0;
        overflow: hidden;
      }
    </style>
    <!--引入three.js-->
    <script src="https://unpkg.com/three@0.122.0/build/three.js"></script>
  </head>

  <body>
  <script>  
      /*
       * 創(chuàng)建場(chǎng)景對(duì)象
       */
      var scene = new THREE.Scene();
      /*
       * 創(chuàng)建網(wǎng)格模型
       */
      var geometry = new THREE.BoxGeometry(200, 200, 200); //創(chuàng)建一個(gè)立方體幾何對(duì)象Geometry
      var material = new THREE.MeshLambertMaterial({
        color: '#f4f4f4',
      }); //材質(zhì)對(duì)象Material
      var mesh = new THREE.Mesh(geometry, material); //網(wǎng)格模型對(duì)象Mesh
      scene.add(mesh); //網(wǎng)格模型添加到場(chǎng)景中
      /*
       * 設(shè)置光源
       */
      var point = new THREE.PointLight('#fff'); //點(diǎn)光源
      point.position.set(300, 100, 200); //點(diǎn)光源位置
      scene.add(point); //點(diǎn)光源添加到場(chǎng)景中
      var ambient = new THREE.AmbientLight('#333');//環(huán)境光
      scene.add(ambient); //環(huán)境光添加到場(chǎng)景中
      /*
       * 設(shè)置相機(jī)
       */
      var width = window.innerWidth; //窗口寬度
      var height = window.innerHeight; //窗口高度
      var k = width / height; //窗口寬高比
      var s = 200; //三維場(chǎng)景顯示范圍控制系數(shù),系數(shù)越大,顯示的范圍越大
      //創(chuàng)建相機(jī)對(duì)象
      var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(200, 300, 200); //設(shè)置相機(jī)位置
      camera.lookAt(scene.position); //設(shè)置相機(jī)方向(指向的場(chǎng)景對(duì)象)
      /*
       * 創(chuàng)建渲染器對(duì)象
       */
      var renderer = new THREE.WebGLRenderer();
      renderer.setSize(width, height); //設(shè)置渲染區(qū)域尺寸
      renderer.setClearColor(0xb9d3ff, 1); //設(shè)置背景顏色
      /*
       * 執(zhí)行渲染操作  
       */
      renderer.render(scene, camera); //指定場(chǎng)景、相機(jī)作為參數(shù)
      document.body.appendChild(renderer.domElement); //body元素中插入canvas對(duì)象
    </script>
  </body>
</html>





















結(jié)語(yǔ)



































下面這幅圖非常形象地說(shuō)明了場(chǎng)景—相機(jī)—渲染器之間的關(guān)系。























































作者:Vam的金豆之路

主要領(lǐng)域:前端開發(fā)

我的微信:maomin9761

微信公眾號(hào):前端歷劫之路