Three.js
?????????WebGL允許把JavaScript和OpenGL 結合在一起運用,但使用WebGL原生的API來寫3D程序非常的復雜,同時需要相對較多的數學知識,對于前端開發者來說學習成本非常高。
????????Three.js是基于webGL的封裝的一個易于使用且輕量級的3D庫,Three.js對WebGL提供的接口進行了非常好的封裝,簡化了很多細節,大大降低了學習成本,極大地提高了性能,功能也非常強大。
????????官網:Three.js – JavaScript 3D Library (threejs.org)
? ? # 下載
? ? GitHub:GitHub - mrdoob/three.js: JavaScript 3D Library.?
? ? # 基礎
????????基于Three.js寫頁面的三要素是:場景(Scene)、相機(Camera)、渲染器(Renderer)
- 場景是一個容器,主要用于保存、跟蹤所要渲染的物體和使用的光源。
- 攝像機對象,攝像機決定了能夠在場景看到什么。
- 渲染器對象,該對象會基于攝像機的角度來計算場景對象在瀏覽器中會渲染成什么樣子。
????????將一個Scene對象和Camera對象傳遞給一個Renderer,它將在相機視錐體內的3D場景的部分作為2D圖像呈現(繪制)到Canvas。?
????????SceneGraph是一個樹狀結構,由各種對象組成,如一個Scene對象、多個Mesh對象、Light對象、Group、Object3D和Camera對象;
????????在圖中,Camera對象有一半是不在SceneGraph中的。這是為了表示在three.js中,不像其他對象,Camera不需要在場景中才能起作用。
? ? 每個添加到Three.js場景的對象,甚至包括THREE.Scene本身,都是繼承自一個名為THREE.Object3D的對象。
? ? ? ? # 入門
? ? ? ? 直接找了其他博主的教程:https://blog.csdn.net/sd1sd2/category_12898367.html
示例一:初始化
? ? ? ? 這里我們參照計算機圖形學:(二)MVP變換示例用Three.js初始化一個立方體,相機看向它:?
<html><head><title>視圖變換基礎案例</title><style>body {margin: 0;overflow: hidden;}canvas {width: 100%;height: 100%;}</style>
</head><body><script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.min.js"></script><script>// 【0】創建一個場景var scene = new THREE.Scene();// 【1】立方體幾何var geometry = new THREE.BoxGeometry(4, 4, 2);// 渲染的基礎材料var materialBasic = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: true });// 這是一種簡單的材質,根據物體表面的法向量計算顏色var materialNormal = new THREE.MeshNormalMaterial();// 創建多材料對象var cube = THREE.SceneUtils.createMultiMaterialObject(geometry, [materialBasic,materialNormal]);// 位置上添加渲染的東西scene.add(cube); // 默認情況下,使用 scene.add() 會將物體加載到(0,0,0) // 【2】做一個相機模擬真實人的視角// 注意,在three.js中的大多數角度都是弧度,但由于某些原因,透視相機需要角度。var camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.set(0, 0, 20);// 觀察位置camera.lookAt(cube.position);// 【3】渲染器var renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 【4】添加聚光燈并且添加到頁面當中var spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(0, 20, 20);spotLight.intensity = 5;scene.add(spotLight);// 【5】添加三維坐標系var axes = new THREE.AxisHelper(6);scene.add(axes);// 最終的渲染renderer.render(scene, camera);</script>
</body></html>
示例二:繞點旋轉
① 以固定角度旋轉相機
????????同計算機圖形學:(二)MVP變換示例一樣,我們需要通過計算相機旋轉后的新位置來更新視圖矩陣,從而達到讓相機以一個固定的旋轉度數繞立方體中心旋轉的效果:
let angle = 0;
let radius = camera.position.z;
const rotationValue = 0.01;var tick = function () {angle += rotationValue;// 更新相機位置(圓形路徑)camera.position.x = radius * Math.sin(angle);camera.position.z = radius * Math.cos(angle);camera.lookAt(cube.position); // 確保相機一直看向物體// 場景改變時,重新執行渲染操作渲染三維場景renderer.render(scene, camera);requestAnimationFrame(tick);
};
tick();
????????軌道控制器(OrbitControls)是 Three.js 中的一個常用工具,用于控制相機的運動。如果目標是實現“相機繞物體旋轉”,直接使用?OrbitControls更簡單:
? ? ? ? 注:這里為了導入OrbitControls模塊,變更了有些API(下述代碼刪減了未做修改的部分)。
<script type="importmap">{"imports": {"three": "https://unpkg.com/three@0.148.0/build/three.module.js","three/examples/jsm/controls/OrbitControls": "https://unpkg.com/three@0.148.0/examples/jsm/controls/OrbitControls.js","three/examples/jsm/utils/SceneUtils": "https://unpkg.com/three@0.148.0/examples/jsm/utils/SceneUtils.js"}}
</script><script type="module">import * as THREE from 'three';import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';import { createMultiMaterialObject } from 'three/examples/jsm/utils/SceneUtils';// 創建多材料對象var cube = createMultiMaterialObject(geometry, [ // 修改前:THREE.SceneUtils.createMultiMaterialObjectmaterialBasic,materialNormal]);// 添加三維坐標系var axes = new THREE.AxesHelper(6); // 修改前:THREE.AxisHelper// 添加軌道控制器const controls = new OrbitControls(camera, renderer.domElement);controls.target.set(cube.position.x, cube.position.y, cube.position.z); // 設置目標點為物體中心controls.autoRotate = true; // 啟用自動旋轉controls.autoRotateSpeed = 1.0; // 旋轉速度var tick = function () {controls.update();renderer.render(scene, camera);requestAnimationFrame(tick);};tick();</script>
????????其他:當對相機繞Y軸進行旋轉時,看起來會是“物體繞相機旋轉”:
var tick = function () {camera.rotateY(0.01);renderer.render(scene, camera);requestAnimationFrame(tick);
};
tick();
② 鼠標拖拽旋轉相機
????????OrbitControls 會監聽鼠標事件(如鼠標移動、鼠標滾輪滾動、鼠標按鍵點擊等),根據用戶的操作實時計算相機應該移動到的新位置和角度,然后更新相機的相關屬性,從而改變相機在 3D 場景中的視角。
const controls = new OrbitControls(camera, renderer.domElement);// 監聽控制器,每次拖動后重新渲染畫面
controls.addEventListener('change', function () {renderer.render(scene, camera); //執行渲染操作
});
? ? ? ? 比起之前做的簡陋版,OrbitControls實現的效果更加絲滑了:?
? ? ? ? 想知道其具體實現可以直接看源碼:THREE:controls/OrbitControls.js(部分源碼解讀:https://zhuanlan.zhihu.com/p/447471816),以及也可以手寫控制器,如three.js鼠標控制物體旋轉