本文轉載于@oxxo的玩轉CSS 3D系列教程第一篇:http://www.oxxostudio.tw/articles/201506/css-3d.html
這篇 CSS 3D 的文章,其實(shí)醞釀已久,從CSS 3D 出來(lái)的時(shí)候就已經(jīng)在關(guān)注,只是要寫(xiě) CSS 3D 真的很費工,里面有太多東西要講,加上最近在做 Webduino 可以改變世界的事業(yè) ( Webduino 超贊呀! ),所以就一直擱著(zhù)了,趁著(zhù)端午放假,一口氣把它搞定吧!
雖然 CSS 3D 并非真的 3D,CSS 3D 坦白說(shuō)就是純粹利用計算的方法,借著(zhù)瀏覽器的高效性能,在 2D 的空間繪制一個(gè) 3D 的圖形,就像我們拿張約,用鉛筆在上頭畫(huà)個(gè)正立方體之類(lèi)的,也因為是借了瀏覽器的運算,自然而然非常地耗性能,往往只要有過(guò)多的形狀轉換為 3D 呈現,就會(huì )發(fā)現電腦的風(fēng)扇開(kāi)始狂轉,這也是使用 CSS 3D 必須要注意的地方,畢竟 CSS 原本就不是拿來(lái)做 3D 應用的技術(shù),可以畫(huà) 3D,只是可以加強 CSS 呈現的美感和能力,但用在精細的 3D 動(dòng)畫(huà)或轉場(chǎng)效果,還是交給專(zhuān)業(yè)的 3D 繪圖軟件來(lái)運行。
從這篇開(kāi)始以及再來(lái)的一兩篇,將會(huì )深入介紹 CSS 3D 的繪圖以及直接做些應用,如果你已經(jīng)會(huì )了 CSS 3D,不妨也可以看看正多面體該如何制作,可以參考這兩篇:玩轉 CSS 3D - 正四面體與正六面體、玩轉 CSS 3D - 正八面體與正十二面體。
我們這邊先來(lái)用 Google SketchUp 這個(gè)免費的 3D 建模軟件,看一下最普通的 3D 繪圖的介面,里頭最基本的會(huì )有三個(gè)元素,第一個(gè):攝影鏡頭,第二個(gè):立體空間,第三個(gè):立體物件。

攝影鏡頭主要定義了觀(guān)看者的角度,就如同我們在拍照,使用長(cháng)焦距的望遠鏡頭,物體可以拉近且不會(huì )變形,使用短焦距的廣角鏡,拍攝的物體就容易變形,從下圖可以看出,鏡頭的焦距可以讓空間內的物體產(chǎn)生不同的變形,至于立體空間則是具備了 X、Y、Z 三個(gè)座標軸的空間,立體物件則是在這個(gè)空間里頭的物件。

所以繪制 CSS 的 3D 圖形,最重要的也就是要架設這三個(gè)物件,不過(guò)因為在 CSS 里並沒(méi)有攝影鏡頭、立體空間...等。這些 3D 軟件才有的元素,所以變成都是用 div 取代,在對應的 div 上頭加入對應的 style 屬性,就可以進(jìn)行模擬,運用上面所提到的三個(gè)元素,我們這里就必須要用到三層div,最外層是攝影鏡頭,第二層為立體空間,第三層是是立體空間內的立體元素,寫(xiě)出來(lái)的 HTML 長(cháng)得就像下面這樣:
<div class="camera"> <div class="space"> <div class="box"></div> </div></div>接著(zhù)就要來(lái)把最外層的 div ( 以下通稱(chēng) camera ) 設定為攝影鏡頭,設定的方法為添加 perspective-origin 以及 perspective 這兩個(gè)屬性,這個(gè)屬性是什么呢?簡(jiǎn)單來(lái)說(shuō)就是透視點(diǎn)以及鏡頭到透視點(diǎn)的距離,如果直接查詢(xún) perspective,看到的八九不離十是下面這些圖案:

然而在 W3C 里頭對于 perspective 的解釋則是下圖這樣,透視點(diǎn)同樣也是物體到攝影機的距離 ( d ) ,但又因為 CSS 的 3D 空間里頭具有 Z 軸,所以 perspective 的距離會(huì )因為 Z 軸的關(guān)系而有所縮放 ( 不過(guò)千萬(wàn)要注意,這里的 Z 指的是物體的 Z 軸,也就是 translateZ,不是攝影機的 )。

此外,perspective-origin 是攝影機的中心點(diǎn)位置,預設相對應空間 div ( 以下都稱(chēng)為 space ) 的中心點(diǎn),不做設定的話(huà),預設都是 center center ( 或 50% 50% ),換句話(huà)說(shuō),作為攝影鏡頭的 camera 的三個(gè)維度,perspective-origin 代表了 X 和 Y 軸,而 perspective 代表 Z 軸 ( 和內容物體的 Z 軸相減才會(huì )變成攝影機的 ),camera 就可以在三維空間里頭進(jìn)行移動(dòng),下圖同樣是 W3C 對于 perspective-origin 所作的解釋?zhuān)敂z影鏡頭往上,圖形的下半部就看不到了。

回到 CSS 來(lái)看的話(huà),我們可以像下面這樣設定,這時(shí)候畫(huà)面完全不是正常的,因為還沒(méi)有設定空間和物體。
.camera{ width:200px; height:200px; perspective-origin:center center; perspective:500px;}攝影機完成后,就是要設定一個(gè)立體空間 space,這個(gè)空間設定的方式很簡(jiǎn)單,只要設定一個(gè)屬性:transform-style,這個(gè)屬性預設為 flat,也就是只要是這個(gè) div 內的子元素,一律都是以扁平 ( flat ) 的方式呈現,所屬的變換 transform 也一律都是用 flat 的方式變換,換句話(huà)說(shuō)就是沒(méi)有 Z 軸的存在,為了讓內容元素都是立體元素,所以我們要將 transform-style 設為 3D,如此一來(lái)內容元素就全部都可以用 3D 進(jìn)行變換,為了方便區分,下面我將 space 外圍多加一個(gè) boder 做區別。
.space{ width:100%; height:100%; border:1px dashed #000; transform-style:3d;}
最后就是內容元素 box 了,我們可以添加一個(gè) 100px x 100px 的 box 進(jìn)去,接著(zhù),用這個(gè) box 來(lái)復習一下前面講的觀(guān)念,在沒(méi)有設定 box 的 traslateZ、rotate 的情形下,不論我們如何去修改 camera 的 perspective-origin 和 perspective,box 的大小和位置都不會(huì )有變化,為什么呢?因為在沒(méi)有設定 box 的 translateZ 或 rotate,讓 Z 的深度有所變化,攝影機透過(guò) perspective 看出去的位置都是相同的,也造成不論怎么去看這個(gè) box 都是一樣的大小。
.box{ width:100px; height:100px; background:#069; transform:translateX(50px) translateY(50px);}

不過(guò)當我們給 box 改變 Z 軸的深度之后 ( 這里我先把 translateZ 設定為 150px ),再去改變 camera 的 perspective-origin 和 perspective,一切彷佛就有了變化。
.box{ width:100px; height:100px; background:#069; transform:translateX(50px) translateY(50px) translateZ(150px); translateZ(150px); translateZ(150px);}
大概了解之后,來(lái)把 box 旋轉一下角度,看得應該就會(huì )更清楚,當攝影機變成廣角,也就是 perspective 變短,整個(gè)旋轉后變形也會(huì )更加明顯,大家可以用開(kāi)發(fā)者工具修改 camera 的 perspective 就會(huì )明白。
.box{ width:100px; height:100px; background:#069; transform:translateX(50px) translateY(50px) rotateY(60deg);}
改變一下 perspective-origin 也會(huì )很有意思。

我們加入多一點(diǎn)的 box,并且讓這些 box 的位置改變或旋轉,看看效果如何,這里比較需要注意的地方,是我們必須要額外在每個(gè) box 加入 position:absolute 的屬性,因為 div 本身為 block 屬性,會(huì )互相擠壓,要設定位置為絕對位置,才會(huì )正確地放在 space 里頭。
.space div{ position:absolute; width:100px; height:100px;}.box1{ background:#069; transform:translateX(50px) translateY(50px) rotateY(60deg);}.box2{ background:#c00; transform:translateX(100px) translateY(20px) rotateX(60deg);}.box3{ background:#f90; transform:translateX(0px) translateZ(-250px) rotateY(20deg);}.box4{ background:#0c9; transform:translateX(20px) translateY(80px) rotateX(-80deg);}
正如上述的三個(gè) 3D 元素,我們就可以輕松的繪制 CSS 3D 圖形,不過(guò)除了 camera、space 和 box 之外,還有一個(gè)最重要最重要最重要的撰寫(xiě)規律在里頭 ( 因為很重要所以要說(shuō)三次 ),這個(gè)規律就是 tramsform 里頭是有順序的,因為 CSS 3D 完全是由 2D 演算而來(lái),并不是真的像 3D 軟件是真的有 3D 的空間,所以就變成會(huì )「按照順序」進(jìn)行演算,而且又因為 transform 會(huì )造成物體的整個(gè)座標軸變換,在順序的編排上就格外重要。
例如今天我先讓 box 在 X 軸上水平位移 100px 再繞著(zhù) Y 軸順時(shí)針轉 60 度,和先繞 Y 軸順時(shí)針轉 60 度,再在 X 軸上頭水平位移 100px 的結果會(huì )完全不同,因為當我先繞了 Y 軸轉動(dòng),整個(gè) X 軸也會(huì )跟著(zhù)轉動(dòng),這時(shí)候再做水平位移,位置就會(huì )像是在深度做變換。
.space div{ position:absolute; width:100px; height:100px;}.box1{ background:#069; transform:translateY(50px) translateX(100px) rotateY(60deg);}.box2{ background:#c00; transform:translateY(50px) rotateY(60deg) translateX(100px);}
transform 的數量少還比較看不出來(lái),當今天 transform 里頭數量一多,造成的差異就更加明顯,這也是在玩 CSS 3D 最最最最最需要注意的重點(diǎn)所在,一定要注意,一定要注意,一定要注意,非常重要所以再說(shuō)三次呀!
.space div{ position:absolute; width:100px; height:100px;}.box1{ background:#069; transform:translateY(50px) translateX(100px) rotateY(60deg) rotateX(60deg) translateX(-50px);}.box2{ background:#c00; transform:translateX(-50px) translateY(50px) rotateX(60deg) rotateY(60deg) translateX(100px);}
以上就是 CSS 3D 的原理解析,坦白說(shuō)如果明白了 3D 的結構組成,CSS 的 3D 就沒(méi)有難度,總而言之,就是先建立好三個(gè)元素:攝影機、立體空間、立體物件,就可以開(kāi)始玩轉 CSS 3D 啰!
本文轉載于@oxxo的玩轉CSS 3D系列教程第一篇:http://www.oxxostudio.tw/articles/201506/css-3d.html
聯(lián)系客服