
宣告:本文涉及圖文和模型素材僅用于個人學習、研究和欣賞,請勿二次修改、非法傳播、轉載、出版、商用、及進行其他獲利行為,
背景
不知不覺,掘金關注者人數已經超過 1000 人,因此特地做了這個頁面紀念一下,感謝大家關注 ???,希望博客園的粉絲也漲漲,后續也將繼續努力,持續輸出一些有價值的文章,本文內容涉及的技術堆疊為 React + Three.js + Stulus,本文中主要包含的知識點包括:圓錐幾何體 ConeGeometry、圓柱幾何體 CylinderGeometry、材質捕捉紋理材質 MeshMatcapMaterial、文字創建和修飾的 FontLoader 和 TextGeometry、使用 Gsap 和它的插件 Physics2DPlugin 創建一些影片、rotateOnAxis 方法實作繞軸自轉等,
對了,后續我專門新建了一個專門針對 Three.js 系列的專欄【Three.js 奧德賽進階之旅】,是掘金簽約的專欄 ??,從基礎入門開始,全方位了解 Three.js 的各種特性,并結合和應用對應特性,實作令人眼前一亮的 Web 創意頁面,進而逐步挖掘 Three.js 和 WebGL 深層次的知識,在這里推廣一下,大家感興趣的話可以關注一波 ??,
效果
頁面 ?? 主體內容主要由四部分組成,分別是:文字 1000!、文字 THANK YOU、掘金三維 Logo、以及 紙片禮花 ??,其中文字各自具有翻轉影片,掘金 Logo 有自轉影片效果,當用 ?? 滑鼠點擊螢屏時,會出現 *★,°*:.☆( ̄▽ ̄)/$:*.°★* , 撒花效果,

打開以下鏈接中的任意一個可以在線預覽效果,本頁面適配PC端和移動端,大屏訪問效果更佳,
?????在線預覽地址1:https://3d-eosin.vercel.app/#/fans?????在線預覽地址2:https://dragonir.github.io/3d/#/fans
實作

?? 資源引入
首先在頂部引入開發必備的資源,除了基礎的 React 和樣式表之外,THREE 是 Three.js 庫;OrbitControls 用于鏡頭軌道控制,可以使用滑鼠移動或旋轉模型;Text 是用于創建文字模型的一個類;Confetti 是一個用于創建禮花效果的類,在后面內容中會做詳細介紹,
import './index.styl';
import React from 'react';
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Text from '@/assets/utils/Text';
import Confetti from '@/assets/utils/Confetti';
?? 頁面結構
頁面主要結構非常簡單,其中 .webgl 用于渲染 3D 元素;.logo 是頁面上的一些圖示裝飾,.github 是存放本專案的 Github 鏈接地址,
<div className='fans_page'>
<canvas className='webgl'></canvas>
<i className='logo'></i>
<i className='logo click'></i>
<a className='github' href='https://github.com/dragonir/3d' target='_blank'></a>
</div>
創建 Logo
創建 Logo 時,先創建一個 Group,然后將 Logo 的各個部分添加到 Group 中,這樣有利于對 Logo 整體調整位置和添加影片,也有利于頁面加載性能,接著,通過以下步驟創建 Logo 模型的三部分:
- 創建通用的材質
MeshMatcapMaterial,Logo模型的所有組成網格都將使用這種材質; - 使用
ConeGeometry創建頂部的四棱錐,并應用材質; - 使用
CylinderGeometry創建中間的四棱臺,并應用材質; - 使用
CylinderGeometry創建底部的四棱臺,并應用材質; - 將上述網格模型添加到
Group中,并調整整體的位置、大小,并設定傾斜角度以便獲得更好的頁面視覺效果,
??在實際開發中,應用了ConeBufferGeometry、CylinderBufferGeometry代替ConeGeometry和CylinderGeometry,以便獲得更好的性能,

本示例中模型的計算引數如上圖所示,頂部四棱柱的四個面都是邊長為 4 的等邊三角形,其余兩個棱臺的側邊長也是 4,其他邊的長度引數都可以通過勾股定理以及三角函式計算得出,本文中不做詳細計算,(PS:模型示意圖是用 Windows 畫圖工具畫的,有點丑 ??)
const logo = new THREE.Group();
// 材質捕捉紋理材質
const logoMaterial = new THREE.MeshMatcapMaterial({
matcap: this.matcaps.logoMatcap,
side: THREE.DoubleSide,
});
// 頂部四棱錐
const cone = new THREE.Mesh(new THREE.ConeGeometry(4, 4, 4), logoMaterial);
logo.add(cone);
// 中間四棱臺
const cylinder = new THREE.Mesh(new THREE.CylinderGeometry(6, 10, 4, 4, 1), logoMaterial);
cylinder.position.y = -6
logo.add(cylinder);
// 底部四棱臺
const cylinder2 = new THREE.Mesh(new THREE.CylinderGeometry(12, 16, 4, 4, 1), logoMaterial);
cylinder2.position.y = -12
logo.add(cylinder2);
logo.position.set(0, 0, 0);
logo.scale.set(11, 11, 11);
// 設定傾斜角度
logo.rotateY(Math.PI * 0.2);
logo.rotateZ(Math.PI * 0.1);
scene.add(logo);

?? 知識點 圓錐幾何體ConeGeometry
圓錐幾何體 ConeGeometry,是一個用于生成圓錐幾何體的類,側面分段數越多則越圓,本例中分段數為 4,所以看起來是個四棱錐,
建構式:
ConeGeometry(radius: Float, height: Float, radialSegments: Integer, heightSegments: Integer, openEnded: Boolean, thetaStart: Float, thetaLength: Float);
引數說明:
radius:圓錐底部的半徑,默認值為1,height:圓錐的高度,默認值為1,radialSegments:圓錐側面周圍的分段數,默認為8,heightSegments:圓錐側面沿著其高度的分段數,默認值為1,openEnded:一個Boolean值,指明該圓錐的底面是開放的還是封頂的,默認值為false,即其底面默認是封頂的,thetaStart:第一個分段的起始角度,默認為0,thetaLength:圓錐底面圓扇區的中心角,通常被稱為θ,默認值是2*PI,這使其成為一個完整的圓錐,
?? 知識點 圓柱幾何體CylinderGeometry
圓柱幾何體 CylinderGeometry,是一個用于生成圓柱幾何體的類,本文中 Logo 的中間和底部就由此類生成,
建構式:
CylinderGeometry(radiusTop: Float, radiusBottom: Float, height: Float, radialSegments: Integer, heightSegments: Integer, openEnded : Boolean, thetaStart: Float, thetaLength: Float)
引數說明:
radiusTop:圓柱的頂部半徑,默認值是1,radiusBottom:圓柱的底部半徑,默認值是1,height:圓柱的高度,默認值是1,radialSegments:圓柱側面周圍的分段數,默認為8,heightSegments:圓柱側面沿著其高度的分段數,默認值為1,openEnded:一個Boolean值,指明該圓錐的底面是開放的還是封頂的,默認值為false,即其底面默認是封頂的,thetaStart:第一個分段的起始角度,默認為0,thetaLength:圓柱底面圓扇區的中心角,通常被稱為θ,默認值是2*PI,這使其成為一個完整的圓柱,
?? 知識點 材質捕捉紋理材質MeshMatcapMaterial
MeshMatcapMaterial 由一個材質捕捉 MatCap或光照球 紋理所定義,其編碼了材質的顏色與明暗,由于 mapcap 影像檔案編碼了烘焙過的光照,因此MeshMatcapMaterial不對燈光作出反應,它可以投射陰影到一個接受陰影的物體上,但不會產生自身陰影或是接收陰影,
建構式:
MeshMatcapMaterial(parameters: Object)
parameters:可選,用于定義材質外觀的物件,具有一個或多個屬性,材質的任何屬性都可以從此處傳入,包括從 Material 繼承的任何屬性,
.color[Color]:材質的顏色,默認值為白色0xffffff,.matcap[Texture]:matcap貼圖,默認為null,- 其他Material基類的共有屬性等,
MeshMatcapMaterial 是一種非常好用的材質,簡單使用這種材質就能實作復雜的紋理效果,如本文中 Logo 的光澤效果,以及后續文字的金屬效果以及透明玻璃效果,選擇合適的材質,可以實作各種各樣的神奇效果,下面這張圖就是本文中所有元素的材質貼圖,可以看出它們是一個個光照球體樣式,

除了在 Blender、Photoshop等設計軟體中生成 MeshMatcapMaterial 之外,下面幾個網站可以免費下載各種好看的材質,并且具有在線實時預覽功能,大家可以根據頁面元素內容和自身需求找到合適的材質圖片,感興趣的話可以親手試試看 ??,

??https://observablehq.com/@makio135/matcaps?ui=classic??https://github.com/nidorx/matcaps

??http://jeanmoreno.com/unity/matcap/http://jeanmoreno.com/unity/matcap/
創建文字 1000!
接著,來創建文字,此時需要引入 FontLoader,用于加載字體檔案,它回傳一個字體實體,然后使用 TextGeometry 創建文字網格,將它添加到場景中就可以了,
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';
fontLoader.load('fontface.json', font => {
textMesh.geometry = new TextGeometry('1000!', {
font: font,
size: 100,
height: 40
});
scene.add(textMesh);
});

看起來非常普通對不對,此時可以對 TextGeometry 進行對字符的厚度、斜角大小等引數的調整,我們可以按類似下面這種稍微優化一下,直至調整到自己滿意的結果為止,
textMesh.geometry = new TextGeometry('1000!', {
font: font,
size: 100,
height: 40,
curveSegments: 100,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 10,
bevelOffset: 2,
bevelSegments: 10
});
看看優化后的效果,瞬間高大上了有木有 ?!

創建文字 THANK YOU
使用同樣的方法添加 THANK YOU 文字網格到場景中,并為它設定半透明玻璃效果的 MeshMatcapMaterial 和文字厚度斜角樣式,

??關于文字網格的詳細應用可以看看我的這篇文章 《使用Three.js實作神奇的3D文字懸浮效果》,本文中不再贅述了,
創建文字影片
文字創建完成后,可以給它們添加一些文字翻轉影片效果,影片效果是通過 Gsap 實作的,本文中給1000! 文字添加了一個縮放并翻轉的影片效果,給 THANK YOU 添加了一個上下翻轉的影片效果,可以參考如下方法來實作,
import gsap from 'gsap';
// 上下翻轉影片
zoomAndFlip() {
gsap.timeline({
repeat: -1,
defaults: {
duration: 2,
ease: 'elastic.out(1.2, 1)',
stagger: 0.1,
},
})
.to(this.meshesPosition, { z: this.meshesPosition[0].z + 100 }, 'start')
.to(this.meshesRotation, { duration: 2, y: Math.PI * 2 }, 'start')
.to(this.meshesRotation, { duration: 2, y: Math.PI * 4 }, 'end')
.to(this.meshesPosition, { z: this.meshesPosition[0].z }, 'end');
}
創建禮花 ??
頁面每次打開以及點擊螢屏時,可以產生禮花效果,其中禮花中的每個小碎片使用了面基礎緩沖模型 PlaneBufferGeometry 以及 MeshBasicMaterial 基礎材質構成,在場景中創建三束禮花,每束禮花內的碎片位置和大小隨機,并在一段時間后自動消失,同樣,禮花的影片效果也是使用了 Gsap,并且使用了它的插件 Physics2DPlugin 來實作,Physics2DPlugin 插件可以模擬物理影片效果包括重力、速度、加速度、摩擦力影片等,有了它就能更好地實作禮花爆炸和散落效果,可以像本文中這樣使用它們:
import gsap from 'gsap';
const physics2D = require('./physics2D');
gsap.registerPlugin(physics2D.Physics2DPlugin);
// 對每一片禮花應用影片效果
gsap.to(this.confettiSprites[id], DECAY, {
physics2D: {
velocity,
angle,
gravity,
friction,
},
ease: 'power4.easeIn',
onComplete: () => {
_.pull(this.confettiSpriteIds, id);
this.parent.remove(this.meshes[id]);
this.meshes[id].material.dispose();
delete this.confettiSprites[id];
},
});
?? 知識點 Physics2DPlugin
Physics2DPlugin 設定二維物理影片拋物線效果可選引數:
velocity:初始速度angle:角度gravity:重力acceleration:加速度accelerationAngle:加速度角度friction:摩擦力
點擊頁面時觸發影片
window.addEventListener('pointerdown', e => {
e.preventDefault();
this.confetti && this.confetti.pop();
});

??文字和禮花效果在實際中實作,其實是分別封裝了兩個類,方便從外部呼叫,具體實作詳細代碼可以訪問文末提供的原始碼鏈接,
縮放監聽及重繪影片
添加頁面縮放適配和重繪影片來更新相機和軌道控制器等,在重繪影片中,給 Logo 添加了一個繞自身 Y軸 旋轉的效果,可以通過 rotateOnAxis 實作,
window.addEventListener('resize', () => {
this.width = window.innerWidth;
this.height = window.innerHeight;
this.camera.aspect = this.width / this.height;
this.camera.updateProjectionMatrix();
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
this.renderer.setSize(this.width, this.height);
}, {
passive: true
});
const animate = () => {
requestAnimationFrame(animate);
controls && controls.update();
// 旋轉影片
logo && logo.rotateOnAxis(axis, Math.PI / 400);
renderer.render(scene, camera);
}
?大家可以親自動手試試rotateOnAxis和rotateY實作的旋轉效果有何不同來區分兩者,
?? 知識點 rotateOnAxis
.rotateOnAxis 是 Three.js 中三維物體基類 Object3D 的一個方法,它可以在區域空間中繞著該物體的軸來旋轉一個物體,假設這個軸已被標準化,它的使用方法如下所示,
.rotateOnAxis(axis: Vector3, angle: Float)
axis:一個在區域空間中的標準化向量,angle:角度,以弧度來表示,
樣式細節優化
到這一步,頁面的功能已經全部完成了 ??,最后可以裝飾一下頁面,如將 renderer 設定為透明,然后在 CSS 中使用一張好看的科技感圖片作為頁面背景,最后加上幾個角落里的圖片裝飾物和 Github 圖示鏈接,加一點點 CSS 影片,頁面整體視覺效果就得到了不錯的提升 ??,最后再次感謝大家關注!??? 謝謝、栓Q、阿里嘎多

??原始碼地址:https://github.com/dragonir/3d/tree/master/src/containers/Fans
總結
本文包含的知識點主要包括:
- 圓錐幾何體
ConeGeometry - 圓柱幾何體
CylinderGeometry - 材質捕捉紋理材質
MeshMatcapMaterial - 文字創建和修飾的
FontLoader和TextGeometry - 使用
Gsap和它的插件Physics2DPlugin創建一些影片 rotateOnAxis方法實作繞軸自轉
想了解其他前端知識或其他未在本文中詳細描述的
Web 3D開發技術相關知識,可閱讀我往期的文章,轉載請注明原文地址和作者,如果覺得文章對你有幫助,不要忘了一鍵三連哦 ??,
附錄
- 新建【Three.js 進階之旅】Three.js 系列專欄 ??
- [1]. ?? Three.js 打造繽紛夏日3D夢中情島
- [2]. ?? Three.js 實作炫酷的賽博朋克風格3D數字地球大屏
- [3]. ?? Three.js 實作2022冬奧主題3D趣味頁面,含冰墩墩
- 更多往期【3D】專欄訪問 ??
...- [1]. ?? 前端實作很哇塞的瀏覽器端掃碼功能
- [2]. ?? 前端瓦片地圖加載之塞爾達傳說曠野之息
- [3]. ?? 使用前端技術實作靜態圖片區域流動效果
- 更多往期【前端】專欄訪問 ??
...
本文作者:dragonir 本文地址:https://www.cnblogs.com/dragonir/p/16691845.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/508119.html
標籤:其他
上一篇:事件流
