本案例為一個 threejs 的特效網(wǎng)頁,大小球體進(jìn)行包裹,外球體為透明材質(zhì),但是進(jìn)行了線框渲染,使其能夠通過外球踢查看其內(nèi)球體。
注:案例參考源于互聯(lián)網(wǎng),在此做代碼解釋,侵刪
本案例除 ThreeJS 外不適用任何第三方框架,放心食用
懶的同學(xué)可以直接下載代碼,打賞作者一根精神食糧:https://download.csdn.net/download/A757291228/87871503
這是 inscode 的代碼,不過渲染有點問題,不過也可以看到大致效果:
一、ThreeJS 三要素
在編寫 ThreeJS 前,需要明白 ThreeJS 的三個要素,若對建模、游戲有過了解的同學(xué)在學(xué)習(xí) ThreeJS 時對知識點理解會更容易接受。
在 ThreeJS 中有三個很關(guān)鍵的對象,分別是 攝像頭、場景以及渲染器:
- 其中 場景 是通過 ThreeJS “搭建”呈現(xiàn)特效的一個“舞臺”,創(chuàng)建好一個場景后,即可往這個場景中添加對應(yīng)的多種物體,例如多邊形、粒子、球體等;
- 創(chuàng)建好場景后我們需要在場景中添加攝像頭用于呈現(xiàn)場景中的視覺效果,攝像頭在 ThreeJS 中擔(dān)任 “視覺采集”
角色,可以通過控制攝像頭采集范圍(大?。亩杉瘓鼍爸幸曈X呈現(xiàn); - 那么完成以上兩步后,還需要對場景進(jìn)行渲染,只有渲染過后才能進(jìn)行視覺效果的呈現(xiàn)。
可以想象場景為一個場地,攝像頭為一個攝像頭,渲染器就是渲染器,然后拍成了一段視頻或照片。
二、代碼中創(chuàng)建三要素
2.1 創(chuàng)建 html
首先創(chuàng)建一個 html 文件,并且引入 CSS 與 JS 文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>1_bit ThreeJS 炫酷旋轉(zhuǎn)多面體Web頁 Demo</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="canvas"></div>
<script src='three.min.js'></script>
<script src="./1bitDemo.js"></script>
</body>
</html>
在此需要注意,在 body 元素中添加了一個 div 并且 id 為 canvas,該 div 是為了之后在 js 代碼中對應(yīng)這個 div 添加渲染好的元素;除此之外還引入了 three.min.js 依賴,另外一個 js 名為 1bitDemo.js 是我們等下須編寫的 js 文件代碼。
2.2 css 編寫
編寫完 html 代碼后,創(chuàng)建一個 style.css 文件用于給 html 添加一些基本樣式,html 設(shè)置背景色,并且給與一個線性漸變,方向向下,隨后給與 margin 為0,使其頁面邊緣貼合,代碼過于簡單在此不再贅述,css 如下:
html {
width: 100%;
height: 100%;
background: linear-gradient(to bottom, #11e8bb 0%, #8200c9 100%);
overflow: hidden;
}
body {
margin: 0;
padding: 0;
}
此時頁面如下:
2.3 創(chuàng)建三要素
接著做完準(zhǔn)備工作后,創(chuàng)建一個 js 文件,在此我的 js 文件名為 1bitDemo.js ,在其中我們將創(chuàng)建 場景、渲染器、攝像頭。
由于我們?yōu)榱艘淮蜷_頁面就進(jìn)行渲染,所以在此需要創(chuàng)建一個 onload 事件:
window.onload = function () {
}
接著創(chuàng)建對應(yīng)的對象存儲三要素(渲染器、場景、攝像頭):
var renderer, scene, camera;
渲染器
我們在此先創(chuàng)建渲染器,通過調(diào)用 THREE 對象的 WebGLRenderer 對攝像頭進(jìn)行創(chuàng)建,WebGLRenderer 方法接收傳入一個渲染器的配置項對象,例如代碼為:
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
此時傳入的配置項:
- antialias 表示抗鋸齒打開,使幾何體邊緣平滑;
- alpha 表示渲染器渲染時的畫面有透明通道,若不打開將不會存在透明通道,例如 png 圖片與 jpg 區(qū)別;
接著配置渲染器的渲染大?。?/p>
renderer.setSize(window.innerWidth, window.innerHeight);
以上代碼中 setSize
方法用于設(shè)置渲染器渲染大小,通過 window.innerWidth
與 window.innerHeight
傳入渲染寬高。
此時就可以通過 js 獲取到 canvas 元素,從而添加渲染器到 canvas 窗口即可:
document.getElementById('canvas').appendChild(renderer.domElement);
以上代碼中 renderer.domElement 是得到渲染器渲染出的 canvas。
場景
場景創(chuàng)建很簡單,通過 THREE
的 Scene
方法即可創(chuàng)建:
scene = new THREE.Scene();
攝像頭
接著創(chuàng)建攝像頭,透視攝像頭創(chuàng)建使用 PerspectiveCamera 方法,代碼如下:
camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 1, 1000);
PerspectiveCamera 方法接收 4 個參數(shù),分別為:
- 相機可視垂直視野角度(玩過FPS的應(yīng)該知道有一個視野角度)
- 相機可視長寬比
- 相機近端距離
- 相機遠(yuǎn)端距離
其中:
- 相機近端距離為 相機到場景中最近可視物體的距離
- 相機遠(yuǎn)端距離為 相機到場景中最遠(yuǎn)的可視物體的距離
若可視物體小于了 相機近端距離 和 大于了 相機遠(yuǎn)端距離 都會不可見。
接著我們此時可以移動一下攝像機的 z 軸,代碼為:
camera.position.z = 500;
以下為 three 中的坐標(biāo)系參考圖:
此時 z 軸就是攝像機,或者說人的視窗所距離中心點的位置,若不移動這個距離,在創(chuàng)建幾何體時將會無法很好的看見幾何體,因為默認(rèn)位置為這個坐標(biāo)系的中心點。
最后將這個攝像機添加到場景中即完成三要素創(chuàng)建:
scene.add(camera);
三、幾何體創(chuàng)建
3.1 創(chuàng)建二十面緩沖幾何體
此時我們創(chuàng)建 2 個二十面的幾何體,直接通過 IcosahedronGeometry 方法即可創(chuàng)建,代碼為:
var geom = new THREE.IcosahedronGeometry(7, 1);
var geom2 = new THREE.IcosahedronGeometry(15, 1);
以上代碼中 IcosahedronGeometry 接受兩個參數(shù),分別為:
- radius 二十面體的半徑,默認(rèn)為1;
- detail 設(shè)置面角,默認(rèn)為0,值超過1則是球體,超過0小于1則會增加頂點使其轉(zhuǎn)變成非二十面幾何體;
3.2 創(chuàng)建二十面體的顯示樣式
在 three 中要為 二十面體創(chuàng)建顯示的樣式需要創(chuàng)建材質(zhì)(Material),在此我們要創(chuàng)建一種可以用來模擬物體表面反射光線的亮度和光滑度的材質(zhì),需要通過 MeshPhongMaterial 進(jìn)行創(chuàng)建,隨后在 MeshPhongMaterial 方法中傳入對應(yīng)的配置項即可:
var mat = new THREE.MeshPhongMaterial({
color: 0xffffff,
shading: THREE.FlatShading
});
var mat2 = new THREE.MeshPhongMaterial({
color: 0xffffff,
wireframe: true,
side: THREE.DoubleSide
});
以上代碼中的配置項對象值:
-
color
表示顏色; -
shading
表示網(wǎng)格的渲染方式(之后要使用的網(wǎng)格),在此使用FlatShading
,表示使用平面著色來渲染網(wǎng)格,渲染的網(wǎng)格將會扁平化; -
wireframe
為true
表示渲染的網(wǎng)格將會呈現(xiàn)線框形式 -
side
設(shè)置為THREE.DoubleSide
表示雙面渲染,即渲染的時候物體雙面都會進(jìn)行渲染,而不是只有一面(性能考慮若想設(shè)置只渲染一面設(shè)置為THREE.FrontSide
)
3.3 創(chuàng)建 Mesh 用于組裝 3D 對象
Mesh 在 ThreeJS 的 3D 對象中是必要的,通過 創(chuàng)建 Mesh 組合 3D 對象,創(chuàng)建 Mesh 需要指定對應(yīng)的幾何體以及材質(zhì),如以下代碼:
var planet = new THREE.Mesh(geom, mat);
其中 geom 為之前所創(chuàng)建的幾何體,mat 為之前所創(chuàng)建的材質(zhì)。
隨后我們需要對這個幾何體 planet 進(jìn)行縮放大小顯示,在此放大 16 倍:
planet.scale.x = planet.scale.y = planet.scale.z = 16;
接下來我們需要創(chuàng)建一個 Object3D 用于存放這個幾何體,通過 Object3D 我們可以方便的對 完整的幾何體進(jìn)行 縮放、移動等。
var center = new THREE.Object3D();
center.add(planet);
scene.add(center);
以上代碼中創(chuàng)建了一個 cente rObject3D 對象,把創(chuàng)建好的幾何體 planet 添加到 center 中,再把 center 添加到 scene 場景中即可。
渲染
此時若想查看頁面是什么樣,可以在末尾直接通過渲染器調(diào)用 render 方法進(jìn)行渲染即可,render 方法需要傳入場景和攝像頭對象,此時代碼為:
renderer.render(scene, camera)
但此時渲染出來的畫面是黑色的:
原因是場景中沒有添加光源,所以暗淡無光,接下來我們創(chuàng)建光源,但在此之前,我們剛剛創(chuàng)建了兩個 MeshPhongMaterial 材質(zhì)和 IcosahedronGeometry 二十面體對象,我們在此只實現(xiàn)了一個對象的 mesh,我們此時再完成另一個 IcosahedronGeometry mesh 的創(chuàng)建,并且創(chuàng)建 Object3D 對象進(jìn)行存放:
var planet2 = new THREE.Mesh(geom2, mat2);
planet2.scale.x = planet2.scale.y = planet2.scale.z = 10;
outside = new THREE.Object3D();
outside.add(planet2);
scene.add(outside);
3.4 創(chuàng)建光源
在此我們創(chuàng)建環(huán)境光,創(chuàng)建環(huán)境光通過方法 AmbientLight,AmbientLight 方法傳入環(huán)境光顏色即可:
var ambientLight = new THREE.AmbientLight(0x999999);
scene.add(ambientLight);
此時刷新界面如下:
此時我們還需要創(chuàng)建其他的太陽光。太陽光通過 DirectionalLight 進(jìn)行創(chuàng)建,是一種平行光,并不會隨距離而衰減。DirectionalLight 接受兩個參數(shù),一個是光照顏色一個是光照強度,光照強度默認(rèn)為 1:
var lights1 = new THREE.DirectionalLight(0xffffff, 1);
lights1.position.set(1, 0, 0);
var lights2 = new THREE.DirectionalLight(0x11E8BB, 1);
lights2.position.set(0.75, 1, 0.5);
var lights3 = new THREE.DirectionalLight(0x8200C9, 1);
lights3.position.set(-0.75, -1, 0.5);
scene.add(lights1);
scene.add(lights2);
scene.add(lights3);
刷新界面重新渲染此時界面如下:
3.5 創(chuàng)建環(huán)境物體
接著開始創(chuàng)建環(huán)境物體,首先依照慣例創(chuàng)建一個 3D 容器,并且將這個容器添加到場景中:
particle = new THREE.Object3D();
scene.add(particle);
接著創(chuàng)建一個四面體(第一個參數(shù)已經(jīng)就是半徑,第二個參數(shù)與二十面體一致):
var geometry = new THREE.TetrahedronGeometry(2, 0);
隨后創(chuàng)建材質(zhì)(與之前一致不再贅述):
var material = new THREE.MeshPhongMaterial({
color: 0xffffff,
shading: THREE.FlatShading
});
由于環(huán)境物體較多,在此直接使用for 循環(huán)進(jìn)行循環(huán)創(chuàng)建:
for (var i = 0; i < 1000; i++) {
var mesh = new THREE.Mesh(geometry, material);
mesh.position.set(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize();
mesh.position.multiplyScalar(90 + (Math.random() * 700));
mesh.rotation.set(Math.random() * 2, Math.random() * 2, Math.random() * 2);//旋轉(zhuǎn)
particle.add(mesh);
}
以上代碼中首先創(chuàng)建了一個 mesh,隨后 通過 mesh.position.set 設(shè)置其 x y z 的坐標(biāo),接著通過 multiplyScalar 方法對坐標(biāo)進(jìn)行放大,此時放大后將會使整體創(chuàng)建的 mesh 位置進(jìn)行擴(kuò)大,遠(yuǎn)離中心點,這樣就可以使這些創(chuàng)建的物體發(fā)散到其他位置,最后在通過 mesh.rotation.set 設(shè)置他們的旋轉(zhuǎn)角度,使創(chuàng)建的物體旋轉(zhuǎn)方向發(fā)生改變,否則都是一個面反光并不是很好看,太單一了,最后添加到 particle 即可完成。
此時頁面效果如下:
為啥看起來球那么?。科鋵嵈蠹铱梢哉{(diào)整視角大小以及遠(yuǎn)端距離可以拉近與物體的距離,在此我把攝像頭視覺方位調(diào)成70:
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
此時呈現(xiàn)效果確實變大了:
最后就是完成動畫,使其旋轉(zhuǎn)。
3.6 animation 動畫
做過 unity 的同學(xué)應(yīng)該很清楚,只需要每幀更改其位置即可,那么此時我們創(chuàng)建一個 animate 方法,設(shè)置其 Object3D 對象的 rotation 即可:
function animate() {
requestAnimationFrame(animate);
particle.rotation.x += 0.0010;
particle.rotation.y -= 0.0040;
inside.rotation.x -= 0.0020;
inside.rotation.y -= 0.0030;
outside.rotation.x -= 0.0010;
outside.rotation.y += 0.0020;
renderer.clear();
renderer.render(scene, camera)
};
以上方法中 requestAnimationFrame 為一個循環(huán)函數(shù),傳入對應(yīng)的函數(shù)名即可重復(fù)執(zhí)行,在此處我們只需要把 這個 animate 函數(shù)放到 onload 事件最后一行代碼即可,并且刪除 onload 中的 renderer 的 render 方法,因為在此處已經(jīng)寫有。
以上代碼中的 renderer.clear(); 為清理渲染器的緩存,準(zhǔn)備下一次渲染,一般在場景重繪前調(diào)用即可,當(dāng)然 clear 可以指定清理不同的緩沖區(qū),同學(xué)們可以之后在了解一下。文章來源:http://www.zghlxwxcb.cn/news/detail-481159.html
以上 animate 方法已經(jīng)寫好了,但是注意 renderer, scene, camera, inside, outside, particle 這些變量需要設(shè)置為全局變量,否則調(diào)用不到。文章來源地址http://www.zghlxwxcb.cn/news/detail-481159.html
到了這里,關(guān)于ThreeJS 炫酷特效旋轉(zhuǎn)多面體Web頁 Demo 01《ThreeJS 炫酷特效制作》的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!