誰會拒絕一款開源的 3D 博客呢?
説到博客大家一定都不陌生,不管你是深耕職場多年的老鳥,還是在學校努力的小鳥,應該都有過一段“裝扮”博客的經歷,比如:放上喜歡的圖片、添加炫酷的交互、換上 DIY 的博客主題等等。但不管再怎麼“打扮”,也跳脱不出平面的“凡胎”。
今天 HelloGitHub 給大家帶來的是一款開源的 3D 博客項目,實話説我第一次訪問這個博客的時候都驚呆了,顛覆了博客的認知。進去後需要通過操控一輛 3D 的小汽車,自己“找到”文章才可以閲讀,特別有意思!
接下來,本文會先介紹如何在本地把項目運行起來,然後講解其源碼和相關技術,最後教你如何修改代碼把自己的博文放進去,升級到 3D 博客!下面讓就讓我們一起走進這個開源的 3D 博客,將驚喜轉化為興趣。
一、介紹
1.1 安裝步驟
話不多説先跑起來再説,只需 4 步。命令如下:
# 1.下載項目
git clone [email protected]:brunosimon/folio-2019.git
# 2.安裝了 Parcel(Web 應用打包工具)
npm install -g parcel-bundler
# 3.安裝依賴(僅第一次需要)
npm i
# 4.運行
npm run dev
提示:這裏就不過多介紹 如何安裝 Node.js 啦!
1.2 運行效果
首先,我們來看看這個博客長什麼樣子:
一輛紅色、可愛的小吉普車,在漫無邊際的地圖上自由地馳騁,還可以按按喇叭助助興,是的沒錯!這個博客還自帶音效。
1.3 小遊戲
正當你“開”着小車唱着歌,突然就被作者創造的這一個 3D 世界給“綁架”了!因為他不止有簡單的模型,還附帶了一些非常有意思的小遊戲。
比如你可以猛地加速撞擊這三面“泡沫牆體”:
又或者是開着小吉普車“打保齡球”:
又或者是做一些“刺激”的越野訓練:
這些小遊戲是不是非常有意思呢?
1.4 關於作者
能寫出這麼有意思的 3D 博客的作者,也是一定是位非常有意思的人,這不他把自己的生活也“刻畫”到了這個項目裏。
我們大致可以猜到這位大佬的日常生活大致是“一人一狗”,而且他非常愛自己的狗狗。除了打遊戲,健身、出門還有其他一些活動都是和它在一起。
啊!多麼愜意的生活呀~這哪裏是程序員的生活呢?這明明就是財富自由的生活啊!你以為這個博客就只是記錄生活點滴那你就錯了,當我們的小吉普駕駛到 “project” 的時候,我們會看到很多作者寫的技術博文。
聊完家常,下面進入代碼的世界!
二、項目概覽
2.1 項目結構
我們先看一下項目結構:
簡單地對這些目錄做一個概述:
是不是有很多文件看不懂?沒關係,我們先從最主要的文件開始,也就大家最熟悉的 src
文件夾,這裏放的都是核心代碼。而且其中最主要的代碼文件,相信你一眼就能看出來,沒錯!就是 index.js
。
import './style/main.css'
import Application from './javascript/Application.js'
window.application = new Application({
$canvas: document.querySelector('.js-canvas'),
useComposer: true
})
這個 index.js
是不是非常簡單,它就是告訴我們其實剛剛看到的所有效果,都是一個 canvas
!而處理邏輯的代碼都來自於 Application.js
,我們這裏摘出一些比較重要的技術棧、項目用到的核心庫,做一個簡單的介紹。
相信很多小夥伴早就猜到了,對!就是 Three.js
。
2.2 Three.js
Three.js 是一個 3D 的 JavaScript 庫,可以讓開發者在 Web 上創造 3D 體驗,它和 WebGL 是最佳拍檔。
那 WebGL 又是個什麼東西呢?WebGL 是一個 JavaScript API,它與大多數現代瀏覽器兼容,且直接使用圖形處理單元 (GPU),這可以實現出色的優化和更多的控制,而且速度很快。
不過原生的 WebGL 難且複雜,使用原生的 WebGL 在畫布上繪製一個三角形至少需要 100 行代碼,在這種情況下再去添加透視、燈光、模型和動畫等等一切東西,可想而知有多令人頭禿了。為了保住程序員為數不多的頭髮,就誕生了 Three.js 庫。它的價值是簡化處理上述所有內容的過程,只需幾行代碼即可獲得動畫 3D 場景。
2.3 dat.gui
這個 3D 博客項目用到的另外一庫是:dat.gui.js,它是一個用於在 JavaScript 中更改變量的輕量級圖形用户界面,使用這個庫可以很容易地創建出能夠改變代碼變量的界面組件。實現的界面大致樣子如下:
三、講解源碼
介紹完重要的技術點,下面繼續回到邏輯處理的核心文件 Application.js
開始講解源碼。
3.1 構建世界
從代碼結構上看,可以看到入口就在 this.setWorld
裏,讓我們來簡單看看這裏的代碼:
constructor(_options)
{
// Options
this.config = _options.config
this.debug = _options.debug
...
// Set up
this.container = new THREE.Object3D()
this.container.matrixAutoUpdate = false
this.setSounds() // 聲音
this.setControls() // 一些按鍵控制等
this.setFloor() // 地板設置
this.setAreas() // 區域設置
this.setStartingScreen() // 首屏動畫(loading > start)
}
相信上面的一些設置你一眼就看懂了,這裏挑幾個可能產生疑惑的方法名再簡單説明一下。this.setControls
主要包含了兩個方法:this.setActions
和 this.setKeyboard
,這裏就是小吉普車行駛和按喇叭等的按鍵控制。
而 this.setFloor
主要是針對當前場景的地板樣式的配置文件,如果你不喜歡原始的配色方案,你大可以自定義一個“五彩斑斕”的顏色,但前提是要具備一定的審美不然可能就翻車如下圖了。
這裏只是針對場景四個角(左上角、右上角、左下角、右下角)的顏色做了自定義,代碼片段如下:
// Colors 修改前
this.colors = {}
this.colors.topLeft = '#f5883c'
this.colors.topRight = '#ff9043'
this.colors.bottomRight = '#fccf92'
this.colors.bottomLeft = '#f5aa58'
// Colors 修改後
this.colors = {}
this.colors.topLeft = 'red'
this.colors.topRight = 'yello'
this.colors.bottomRight = 'blue'
this.colors.bottomLeft = 'black'
剩下的 this.setAreas
主要是針對一些鼠標事件做了處理,便於我們用鼠標拖動和探索整個“世界”,包含了 mousemove
、mousedown
、touchstart
等,相關代碼就不貼出來了,感興趣的可以自行探索~
3.2 開始之後
以上這些構建都是在開始頁面出現的時候執行的代碼,相當於提前做了一部分資源加載,那剩下的一些加載就在我們點擊「start」之後開始。
在 World.js
文件裏,我們也可以找到相應的代碼 this.start
。
// On interact, reveal 點擊 start 的交互
this.startingScreen.area.on('interact', () =>
{
TweenLite.to(this.startingScreen.startLabel.material, 0.3, { opacity: 0, delay: 0.4 })
// 剩下的資源加載
this.start()
window.setTimeout(() =>
{
this.reveal.go()
}, 600)
})
在 start
這個方法裏面我們會看到更多內容的加載,比如小吉普車的加載,還有我們最想知道的文章列表的加載。
start()
{
this.setCar() // 汽車加載
this.areas.car = this.car
this.setSections() // 文章加載
}
沒錯就是它,接下來我們要找文章入口的方向標。即 x 和 y 軸表示這個對象在畫布上的座標位置,我們也可以挪到自己喜歡的位置上去。
// Projects
this.sections.projects = new ProjectsSection({
...options,
x: 30,
y: - 30
})
這裏需要稍微介紹下 Three.js
的座標軸系,它採用右手座標系, 如下圖所示,與此對應的還有左手座標系:
所以,當我們加大 x 的值後,我們會發現整個文章距離變得遠了,同理修改 y 值也是同樣的效果。
3.3. 文章列表
查看 ProjectsSection.js
文件,我們發現裏面有很多的圖片,先別管往下看就會看到一個 setList
,改動如下:
setList()
{
this.list = [
{
name: 'HelloGitHub',
imageSources:
[
projectsThreejsJourneySlideESources
],
floorTexture: this.resources.items.projectsThreejsJourneyFloorTexture,
link:
{
href: 'https://hellogithub.com/',
// 控制按鈕的位置
x: - 5.8,
y: - 4.5,
// 控制open按鈕大小(0,0)的時候無邊框
halfExtents:
{
x: 2,
y: 1
}
},
distinctions:
[
// 一個3d模型的圖標,xy是座標軸位置
{ type: 'fwa', x: 4.15, y: 5.15 }
]
}
]
}
如此一來,你就擁有了“自己”的 3D 博客,只不過謙虛一點來説,3D 是別人的,博客是你自己的。來張特寫看看:
結合圖片我們對上面的代碼做一些解釋:
1. imageSources
:就是“廣告牌”上面的圖片,我這裏只弄了一張 HelloGitHub 社區首頁的圖片,你也可以按照原博客那樣放上好幾張圖。
圖片存放的地址和引入規則:
import projectsThreejsJourneySlideESources from '../../../models/projects/threejsJourney/slideE.jpg'
2. floorTexture
即“地板貼圖”,也就是我們看到“躺”在地上的那個圖,或許你會問:為什麼不能直接把圖放上去還需要變成一個 texture
貼圖呢?
因為,這是一個 3D 世界,隨着鼠標上下拖動,我們對於這個圖的視覺會發生變化,所以需要把圖也“放”到一個 3D 容器中去,這樣我們所構建的 3D 世界才真實可信。所以這裏我們跟着代碼去倒推這個圖是怎麼生成。
floorTexture: this.resources.items.projectsThreejsJourneyFloorTexture,
我們得知它是“掛”在 resources
對象下面的。一層一層查下去,我們發現他是在 Application.js
的時候加載進來的。進到 Resources.js
文件,我們可以發現有非常多的資源文件例如 .png
、.glb
之類的。
什麼是 glb 文件?
上文提到的 .glb
後綴的文件,它包含以 GL 傳輸格式(glTF)保存的三維模型。它以二進制格式存儲有關三維模型的信息,例如節點層次結構、攝影機和材質、動畫和網格。.glb
文件是 .glTF
文件的二進制版本。
3.4 再深入一點
接着上面探究:貼圖是怎麼生成的,順着 Resources.js
文件接着看。
如果,直接在 Resources.js
裏面直接搜上面的 projectsThreejsJourneyFloorTexture
關鍵詞是搜不到的,那就刪掉後面的一些英文再試試,我們會發現這樣的一行代碼在 this.loader.load
這個方法裏:
{ name: 'projectsThreejsJourneyFloor', source: projectsThreejsJourneyFloorSource, type: 'texture' },
跟着它的 source
字段再搜,會發現它關聯的圖片文件:
import projectsThreejsJourneyFloorSource from '../models/projects/threejsJourney/floorTexture2.png'
你肯定好奇,為什麼直接搜搜不到呢?讓我們摺疊長代碼再來看一下,你就會發現有一個名字的處理函數:
this.loader.on('fileEnd', (_resource, _data) =>
{
this.items[_resource.name] = _data
// Texture
if(_resource.type === 'texture')
{
const texture = new THREE.Texture(_data)
texture.needsUpdate = true
this.items[`${_resource.name}Texture`] = texture
}
// Trigger progress
this.trigger('progress', [this.loader.loaded / this.loader.toLoad])
})
沒錯,處理函數會自動加上 Texture
作為對象名的後綴,可以説是非常嚴謹了,因為他從一個普通的圖片文件變成了一個“貼圖”文件,要貼合在 3D 容器裏面。
現在,我們再回到上面的 setList
方法。其它的文件鏈接、模型的座標軸位置,相信你已經對它們一目瞭然!
五、結尾
閲讀源碼一定不是一個容易的過程,尤其是從初學者開始。雖然難熬但也經常有一些小驚喜激勵着我,比如:一遍又一遍地閲讀源碼的過程中,突然發現一個小小的知識點,還是挺有意思的。
舉個例子,這個 3D 博客項目中很多這樣的圖片:
點開就是一張黑不溜秋的圖片,起初我根本就不知道這是什麼東西,但隨着我對代碼的理解加深。突然恍然大悟,原來這些是模型的位置和陰影效果渲染。
最後,這一趟短暫的 3D 博客入門之旅到這裏,就要跟各位乘客説再見了。其實整個原文件的內容非常豐富,包括很多 3D 模型的文件、打包的配置優化等等,值得更加深入和系統地學,但是由於篇幅和能力有限,今天就先寫到這裏。如果你有興趣翻閲源碼的話,你會有更多意想不到的發現。
以上就是本文的所有內容,如果您覺得這篇文章寫得還不錯,就請給我點一個贊,您的支持就是我更新的動力。
- 開源月刊《HelloGitHub》第 84 期
- 10 款開源的在線遊戲,點開就能玩的那種
- 窮人版生產力工具,好用得飛起 「GitHub 熱點速覽」
- GPT-4 來了!這些開源的 GPT 應用又要變強了
- 誰會拒絕一款開源的 3D 博客呢?
- 你的夢想家居「GitHub 熱點速覽」
- 開箱即用,你不可錯過的好東西「GitHub 熱點速覽」
- AI 能多強「GitHub 熱點速覽」
- 開源月刊《HelloGitHub》第 83 期
- 真·生產力「GitHub 熱點速覽」
- 如何讓程序更健壯「GitHub 熱點速覽」
- 朋友圈那串神祕字符背後的開源項目「GitHub 熱點速覽」
- 讓人眼前一亮的應用「GitHub 熱點速覽」
- 2023 年該學點什麼技術?「GitHub 熱點速覽 v.23.03」
- 開源月刊《HelloGitHub》第 82 期
- 忙活了一年的開源社區,終於趕上了春節前的末班車!
- 過年必備!親戚計算器「GitHub 熱點速覽 v.23.02」
- Windows 11 內核新調試器「GitHub 熱點速覽 v.23.01」
- HelloGitHub 最受歡迎的開源項目 Top10(2022年)
- 你的 GitHub 年度報告「GitHub 熱點速覽 v.22.52」