在近20年的前端發展史中,前端經歷了鐵器時代(小前端),信息時代(大前端)以致如今的全能前端時代。經歷了幾個時代的沉澱以後,前端領域開始更加細分。前端
目前業界廣泛認爲前端細分領域的垂直方向有:助力於先後端分離和工程完善的NodeJS,關注用戶界面展現的小前臺,提供一站式解決方案的中後臺,豐富數據展現能力的數據可視化(2D、3D),以及面向將來的用戶富交互體驗的互動內容--AR、VR、3D等...java
隨着前端領域細分,前端工程師已不僅是簡單的負責堆砌網頁、實現一些的交互,更能夠在可視化領域實現一些很炫酷的效果。下圖是vivo官網在3D數據可視化方面的實戰展現。在線體驗地址git
數據可視化: 顧名思義,就是將數據以可視化圖形圖表等方式呈現給用戶,使數據更加直觀,客觀,說服力更強。上圖例就是利用渲染引擎對模型數據進行解析、渲染,最終呈現到移動設備。因其展示出的圖像更加立體更具可交互性,屬於3D數據可視化範疇。github
今天咱們就一塊兒來了解一下前端的一個細化分支--3D數據可視化。本篇文章主要分爲:web
但願經過五個章節的介紹和探討,可以可讓你們對數據可視化以及3D數據可視化有一個較爲清晰的瞭解。npm
2D數據可視化是指利用二維平面圖表對數據進行組織處理、呈現的一種方式。講到圖表,你們首先想到的多是咱們平常用過柱狀圖,折線圖等展現形式的圖表圖形。好比下面這種:json
其實除了上面幾種形式,還有一些比較炫酷的圖表展現形式如:氣泡圖、面積圖、省份地圖、詞雲、瀑布圖、漏斗圖、熱力圖、GIS地圖等。後端
2D數據可視化在工做生活中的應用很是普遍。最簡單的像Excel數據圖表,XMind、Visio屬於數據可視化的具體應用場景。也有一些稍微複雜的,好比數據可視化大屏,後臺數據報表,地圖等。瀏覽器
隨着數據可視化的應用場景愈來愈普遍,數據能夠呈現爲更多豐富的可視化形式,使用戶可以更加輕易、便捷的獲取並理解數據傳達的信息。性能優化
3D數據可視化能夠理解爲在2D數據可視化的基礎上增長了Z軸的維度,使數據呈現從二維平面擴展到三維立體結構。是一種新的管理、分析和交互數據的方式,而且能實現實時反射、實時折射、動態陰影等高品質,逼真實時渲染3D圖像。
3D數據可視化與2D數據可視化(通常數據可視化)主要區別就是更立體,更真實,更有沉浸感。來張圖感覺一下:
3D數據可視化因其知識傳輸速度快、數據信息展現更直觀、信息傳達更容易,因此更加容易讓使用者進行數據的理解和空間知識的呈現。
目前可見的3D數據可視化應用領域有智慧城市、汽車、手機模型展現等。
相信隨着瀏覽器對WebGL的支持度愈來愈廣,以及5G的普及,前端3D可視化的應用領域會愈來愈普遍。
瞭解了3D數據可視化的概念和應用場景,咱們再來了解下目前業界3D數據可視化主流解決方案:WebGL。
下圖爲WebGL的渲染過程圖:
WebGL(Web Graphics Library) 是基於 OpenGL ES 規範的瀏覽器實現,上圖的WebGL渲染過程能夠理解爲:
1)JavaScript: 處理着色器須要的頂點座標、法向量、顏色、紋理等信息,併爲頂點着色器提供這些數據
2)頂點着色器: 接收 JavaScript 傳遞過來的頂點信息,將頂點繪製到對應座標
3)光柵化階段: 將圖形內部區域用空像素進行填充
4)片元着色器: 爲圖形內部的像素填充顏色信息
5)渲染: 渲染到Canvas對象
WebGL既能夠繪製2D數據可視化圖形圖表,更是一種 3D 繪圖標準,這種繪圖技術標準將JavaScript 和 OpenGL ES 2.0 結合在一塊兒,經過綁定, WebGL能夠爲 HTML5 Canvas 提供硬件 3D 加速渲染,這樣 咱們就能夠藉助系統顯卡來在瀏覽器裏更流暢地展現 3D 場景和模型。
對用戶來說,網上購物最大的痛點就是不能所見即所得,目前主流的網上商城通常都是經過圖片或者視頻展現產品的特色,而這些二維的信息展現方式沒法讓用戶很好的去了解產品的信息。有了3D展現場景以後,用戶經過手機模型的3D展現能夠更加直觀清楚的瞭解手機的產品細節及特色,從而提高用戶的購買慾望。
下面咱們一塊兒來了解下vivo官網在實現3D展現時的技術選型及實現方案。
目前,業界已經有不少好用的3D可視化開發工具,方便咱們進行3D可視化需求的開發。3D數據可視化主要包含渲染庫和模型兩方面,下面咱們從3D渲染庫和模型分別瞭解下3D可視化領域工具及官網的技術選型。
目前實現3D數據可視化的主流解決方案是基於WebGL,那既然有了WebGL,咱們爲何還須要渲染庫?
這是由於WebGL門檻相對較高,須要理解掌握相對較多的數學知識。雖然WebGL提供的是面向前端的API,但本質上WebGL跟前端開發徹底是兩個不一樣的方向,知識的重疊不多。
利用渲染庫進行模型的渲染實現能夠大大下降咱們的學習成本,而且可以完成WebGL所能實現的幾乎一切功能。經常使用的一些3D渲染庫有:ThreeJs、BabylonJS、SceneJS以及CesiumJs;
幾種不一樣3D渲染庫對比:
經過對比咱們能夠發現,上述幾種渲染庫各有優勢。可是在作手機模型的3D渲染時,對於光照和陰影以及反射的側重點比較高,並不須要碰撞檢測等特性。因此,基於以上的對比,咱們選取ThreeJs做爲咱們3D渲染的底層庫去實現手機模型的3D渲染。
瞭解了渲染庫,咱們再來聊一聊經常使用的3D模型格式:OBJ、FBX、GLTF。
模型文件實際上是一個包含了頂點座標、索引(index)、UV、法線、節點關係、材質、貼圖、動畫等信息的數據集合。不論模型格式如何,可是其本質就是對上述信息的編排和組織。各類模型之間的區別無非是組織的方式不一樣,有些用純文本(OBJ),有些用json(GLTF),有些用二進制(FBX)。
幾種不一樣模型文件對比:
經過對比咱們發現幾種模型格式分別適用於不一樣的場景:
1)OBJ模型對於動畫的支持不是特別友好,而手機在作3D展現時須要進行一些模型的拆解動畫展現。
2)FBX 因爲不一樣引擎解析的規範不一樣,致使不一樣引擎渲染出的效果差異較大
3)GLTF(GLB) 模型格式擴展性較高,ThreeJs、Babylonjs等WebGL渲染引擎的支持性較好
咱們發現,若是想要將3D場景中的物體展現的足夠逼真,相機和光照是必不可少的兩個基本要素。實際業務場景中還有模型顏色切換、模型旋轉、縮放、全景場景等邏輯須要咱們去處理。
首先,咱們來了解一下相機。3D場景中的相機相似於現實生活中的人眼的功能。相機拍攝一個物體的時候相機的位置和角度須要設置,虛擬的相機還須要設置投影方式。位置和角度咱們比較好理解,下面咱們來介紹下投影方式:投影有兩種方式,分別是正投影與透視投影:
正投影: 正射投影,又叫平行投影。這種投影的視景體是一個矩形的平行管道,也就是一個長方體,如圖所示。正射投影的最大一個特色是不管物體距離相機多遠,投影后的物體大小尺寸不變。
正投影一般用在建築藍圖繪製和計算機輔助設計等平面圖形方面,這些行業要求投影后的物體尺寸及相互間的角度不變,以便施工或製造時物體比例大小正確。
透視投影: 透視投影符合人們心理習慣,即離視點近的物體大,離視點遠的物體小,遠到極點即爲消失,成爲滅點。它的視景體相似於一個頂部和底部都被切除掉的棱椎,也就是棱臺。
透視投影一般用於動畫、視覺仿真以及其它許多具備真實性反映的方面。相比較來說,透視投影則更接近咱們的視覺感知。因此在官網的手機模型3D展現中,咱們選擇透視投影來計算相機的投影矩陣。
4.2.2 場景光照
要想讓咱們渲染出的 3D 物體看起來更天然、逼真,很重要的一點就是模擬各類光照的效果。
3D場景中物體的光照由光源、介質(物體的材質)和反射類型決定的,而反射類型又由物體的材質特色決定。根據不一樣的光源特色,咱們能夠將光源分爲 4 種不一樣的類型。
分別是環境光(Ambient Light)、平行光(Directional Light)、點光源(Positional Light)。
咱們分別來了解下環境光(Ambient Light)、平行光(Directional Light)、點光源(Positional Light)。
從圖中咱們能夠看出:
平行光是朝着某個方向照射的光,光線中的每個光子與其它光子都是平行運動的。舉個例子,陽光就能夠認爲是平行光,平行光只能照亮物體的一部分表面。
平行光除了顏色以外,同時具備方向屬性,屬於有向光。有向光和物體發生做用時根據物體的材質不一樣,會產生漫反射和鏡面反射兩種反射效果。3D場景中最終的反射效果是由環境光、平行光,漫反射以及鏡面反射疊加在一塊兒的效果。
點光源是指光線是從一個點發射出來的,是向着四面八方發射的。這種光在咱們的現實生活中是最常被用到的。舉個例子,電燈泡就是向各個方向發射光線的,它就能夠被認做是點光源。
點光源不只有方向屬性,還有位置屬性。所以計算點光源的光照,咱們要先根據光源位置和物體表面相對位置來肯定方向,而後再和平行光同樣,計算光的方向和物體表面法向的夾角。
環境光就是指物體所在的三維空間中自然的光,它充滿整個空間,在每一處的光照強度都同樣。環境光沒有方向,因此,物體表面反射環境光的效果,只和環境光自己以及材質的反射率有關。
有了相機和光照就可以比較逼真的將模型呈現給用戶了,可是還須要處理模型自己的一些交互操做,好比模型旋轉、顏色切換等。實現3D場景中的模型旋轉有兩種實現方式:
(1)3D場景中的相機不動,旋轉3D實體即3D模型
(2)旋轉相機,即3D模型不動,相機圍繞模型進行旋轉
在現實生活中,將物體移動到視場中並非正確的方法,由於在實際生活中一般是移動相機去拍攝建物體。因此咱們選擇移動相機 即實現方式(1) 去實現3D實體的旋轉交互。
4.2.4 模型顏色切換
模型格式採用的是GLB模型(方便後期固化上傳),因此每一種顏色對應一個新的GLB文件。
每一次切換模型須要從新對文件進行解析,可是因爲不一樣顏色模型間貼圖等材質能夠共用,因此即便切換顏色時從新加載模型並解析也會比初始加載時的速度提高不少。因此考慮到後期的固化成本與複用性,切換顏色從新加載模型文件,不失爲一種相對比較優雅的處理方式。
4.2.5 全景場景搭建
爲了讓用戶在瀏覽產品的3D頁面時有更強的沉浸體驗。咱們採用了全景模式。用戶在全景模式下旋轉縮放手機時,對應的背景元素一樣會跟隨相機的旋轉和縮放進行旋轉縮放。這樣用戶在進行瀏覽查看時,交互的體驗感更強。
在ThreeJs中全景模式能夠經過加載紋理貼圖的方式實現:
let texture = await Loader.loadImg(panoramicImg) texture.encoding = THREE.sRGBEncoding let sphereGeometry = new THREE.SphereGeometry(3000, 160, 160) sphereGeometry.scale(-1, 1, 1) let sphereMaterial = new THREE.MeshBasicMaterial({ map: texture }) let sphere = new THREE.Mesh(sphereGeometry, sphereMaterial) // 設置材質對象的紋理貼圖 this.bgMap = sphere this.stage.scene.add(this.bgMap)
上面代碼首先建立一個球形幾何SphereGeometry,將建立後的球形幾何網格進行x軸反轉:sphereGeometry.scale(-1, 1, 1),使全部的麪點向內。而後加載圖片數據建立材質並加入map:new THREE.MeshBasicMaterial({map:texture});new THREE.Mesh(sphereGeometry, sphereMaterial) 最終實現全景圖效果。
爲了提高頁面初始化的加載速度以及切換顏色模型時的解析速度,咱們在製做完成模型後,須要對模型進行壓縮以下降模型的體積量。
谷歌針對GLB模型有一個壓縮庫Draco 3D,能夠在不影響模型展現效果的狀況下,對模型的體積進行壓縮。能夠利用GLTF Pipeline命令行對GLTF模型進行壓縮。
壓縮的步驟:
一、安裝gltf-pipeline
npm install -g gltf-pipeline
二、轉換gltf至glb文件
Converting a glTF to glb gltf-pipeline -i model.gltf -o model.glb gltf-pipeline -i model.gltf -b
壓縮以後,glb文件的體積會減小80%左右,因此在加載速度和效果呈現上會比原始的GLTF文件更快。
4.3.2 模型解壓縮
ThreeJs有針對壓縮模型的解壓縮方案:
// Instantiate a loader const loader = new GLTFLoader(); // Optional: Provide a DRACOLoader instance to decode compressed mesh data const dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath( '/examples/js/libs/draco/' ); loader.setDRACOLoader( dracoLoader );
首先構建一個GLTFLoader對象,而後在進行模型加載過程當中,設置dracoLoader解析文件的路徑,dracoLoader對壓縮後的模型文件進行解析。最後將解析後的文件返回至腳本進行渲染呈現。
本篇文章首先介紹了2D數據可視化,經過將平面圖表數據可視化形式拉伸到三維立體結構,衍生出了3D數據可視化相關內容,以及官網基於ThreeJs的3D應用開發實戰。
可是WebGL關於3D渲染相關的知識遠不止這些。這裏只是列舉出了比較經常使用的幾種3D模型的渲染要素,好比燈光,相機等。實際還有關於物體材質的光的反射類型:漫反射、鏡面反射,相機也有其餘類型的相機模型:例如:正交相機、立方相機、立體相機等,因爲篇幅緣由咱們再也不作詳細的介紹,感興趣的同窗能夠去(WebGL)官網去查看並學習相關內容。
做者:vivo 官網商城前端團隊-Ni Huaifa