本文轉(zhuǎn)載于@oxxo的玩轉(zhuǎn)CSS 3D系列教程第一篇:http://www.oxxostudio.tw/articles/201506/css-3d.html
這篇 CSS 3D 的文章,其實醞釀已久,從CSS 3D 出來的時候就已經(jīng)在關(guān)注,只是要寫 CSS 3D 真的很費工,里面有太多東西要講,加上最近在做 Webduino 可以改變世界的事業(yè) ( Webduino 超贊呀! ),所以就一直擱著了,趁著端午放假,一口氣把它搞定吧!
雖然 CSS 3D 并非真的 3D,CSS 3D 坦白說就是純粹利用計算的方法,借著瀏覽器的高效性能,在 2D 的空間繪制一個 3D 的圖形,就像我們拿張約,用鉛筆在上頭畫個正立方體之類的,也因為是借了瀏覽器的運算,自然而然非常地耗性能,往往只要有過多的形狀轉(zhuǎn)換為 3D 呈現(xiàn),就會發(fā)現(xiàn)電腦的風(fēng)扇開始狂轉(zhuǎn),這也是使用 CSS 3D 必須要注意的地方,畢竟 CSS 原本就不是拿來做 3D 應(yīng)用的技術(shù),可以畫 3D,只是可以加強 CSS 呈現(xiàn)的美感和能力,但用在精細的 3D 動畫或轉(zhuǎn)場效果,還是交給專業(yè)的 3D 繪圖軟件來運行。
從這篇開始以及再來的一兩篇,將會深入介紹 CSS 3D 的繪圖以及直接做些應(yīng)用,如果你已經(jīng)會了 CSS 3D,不妨也可以看看正多面體該如何制作,可以參考這兩篇:玩轉(zhuǎn) CSS 3D - 正四面體與正六面體、玩轉(zhuǎn) CSS 3D - 正八面體與正十二面體。
我們這邊先來用 Google SketchUp 這個免費的 3D 建模軟件,看一下最普通的 3D 繪圖的介面,里頭最基本的會有三個元素,第一個:攝影鏡頭,第二個:立體空間,第三個:立體物件。
攝影鏡頭主要定義了觀看者的角度,就如同我們在拍照,使用長焦距的望遠鏡頭,物體可以拉近且不會變形,使用短焦距的廣角鏡,拍攝的物體就容易變形,從下圖可以看出,鏡頭的焦距可以讓空間內(nèi)的物體產(chǎn)生不同的變形,至于立體空間則是具備了 X
、Y
、Z
三個座標(biāo)軸的空間,立體物件則是在這個空間里頭的物件。
所以繪制 CSS 的 3D 圖形,最重要的也就是要架設(shè)這三個物件,不過因為在 CSS 里並沒有攝影鏡頭、立體空間...等。這些 3D 軟件才有的元素,所以變成都是用 div
取代,在對應(yīng)的 div
上頭加入對應(yīng)的 style 屬性,就可以進行模擬,運用上面所提到的三個元素,我們這里就必須要用到三層div
,最外層是攝影鏡頭,第二層為立體空間,第三層是是立體空間內(nèi)的立體元素,寫出來的 HTML 長得就像下面這樣:
<div class="camera"> <div class="space"> <div class="box"></div> </div></div>
接著就要來把最外層的 div
( 以下通稱 camera ) 設(shè)定為攝影鏡頭,設(shè)定的方法為添加 perspective-origin
以及 perspective
這兩個屬性,這個屬性是什么呢?簡單來說就是透視點以及鏡頭到透視點的距離,如果直接查詢 perspective
,看到的八九不離十是下面這些圖案:
然而在 W3C 里頭對于 perspective
的解釋則是下圖這樣,透視點同樣也是物體到攝影機的距離 ( d
) ,但又因為 CSS 的 3D 空間里頭具有 Z
軸,所以 perspective
的距離會因為 Z
軸的關(guān)系而有所縮放 ( 不過千萬要注意,這里的 Z
指的是物體的 Z
軸,也就是 translateZ
,不是攝影機的 )。
此外,perspective-origin
是攝影機的中心點位置,預(yù)設(shè)相對應(yīng)空間 div
( 以下都稱為 space ) 的中心點,不做設(shè)定的話,預(yù)設(shè)都是 center center
( 或 50% 50%
),換句話說,作為攝影鏡頭的 camera 的三個維度,perspective-origin
代表了 X
和 Y
軸,而 perspective
代表 Z
軸 ( 和內(nèi)容物體的 Z
軸相減才會變成攝影機的 ),camera 就可以在三維空間里頭進行移動,下圖同樣是 W3C 對于 perspective-origin
所作的解釋,當(dāng)攝影鏡頭往上,圖形的下半部就看不到了。
回到 CSS 來看的話,我們可以像下面這樣設(shè)定,這時候畫面完全不是正常的,因為還沒有設(shè)定空間和物體。
.camera{ width:200px; height:200px; perspective-origin:center center; perspective:500px;}
攝影機完成后,就是要設(shè)定一個立體空間 space,這個空間設(shè)定的方式很簡單,只要設(shè)定一個屬性:transform-style
,這個屬性預(yù)設(shè)為 flat
,也就是只要是這個 div
內(nèi)的子元素,一律都是以扁平 ( flat
) 的方式呈現(xiàn),所屬的變換 transform
也一律都是用 flat
的方式變換,換句話說就是沒有 Z
軸的存在,為了讓內(nèi)容元素都是立體元素,所以我們要將 transform-style
設(shè)為 3D
,如此一來內(nèi)容元素就全部都可以用 3D 進行變換,為了方便區(qū)分,下面我將 space 外圍多加一個 boder
做區(qū)別。
.space{ width:100%; height:100%; border:1px dashed #000; transform-style:3d;}
最后就是內(nèi)容元素 box 了,我們可以添加一個 100px x 100px
的 box 進去,接著,用這個 box 來復(fù)習(xí)一下前面講的觀念,在沒有設(shè)定 box 的 traslateZ
、rotate
的情形下,不論我們?nèi)绾稳バ薷?camera 的 perspective-origin
和 perspective
,box 的大小和位置都不會有變化,為什么呢?因為在沒有設(shè)定 box 的 translateZ
或 rotate
,讓 Z
的深度有所變化,攝影機透過 perspective
看出去的位置都是相同的,也造成不論怎么去看這個 box 都是一樣的大小。
.box{ width:100px; height:100px; background:#069; transform:translateX(50px) translateY(50px);}
不過當(dāng)我們給 box 改變 Z
軸的深度之后 ( 這里我先把 translateZ
設(shè)定為 150px
),再去改變 camera 的 perspective-origin
和 perspective
,一切彷佛就有了變化。
.box{ width:100px; height:100px; background:#069; transform:translateX(50px) translateY(50px) translateZ(150px); translateZ(150px); translateZ(150px);}
大概了解之后,來把 box 旋轉(zhuǎn)一下角度,看得應(yīng)該就會更清楚,當(dāng)攝影機變成廣角,也就是 perspective
變短,整個旋轉(zhuǎn)后變形也會更加明顯,大家可以用開發(fā)者工具修改 camera 的 perspective
就會明白。
.box{ width:100px; height:100px; background:#069; transform:translateX(50px) translateY(50px) rotateY(60deg);}
改變一下 perspective-origin
也會很有意思。
我們加入多一點的 box,并且讓這些 box 的位置改變或旋轉(zhuǎn),看看效果如何,這里比較需要注意的地方,是我們必須要額外在每個 box 加入 position:absolute
的屬性,因為 div
本身為 block 屬性,會互相擠壓,要設(shè)定位置為絕對位置,才會正確地放在 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);}
正如上述的三個 3D 元素,我們就可以輕松的繪制 CSS 3D 圖形,不過除了 camera、space 和 box 之外,還有一個最重要最重要最重要的撰寫規(guī)律在里頭 ( 因為很重要所以要說三次 ),這個規(guī)律就是 tramsform
里頭是有順序的,因為 CSS 3D 完全是由 2D 演算而來,并不是真的像 3D 軟件是真的有 3D 的空間,所以就變成會「按照順序」進行演算,而且又因為 transform
會造成物體的整個座標(biāo)軸變換,在順序的編排上就格外重要。
例如今天我先讓 box 在 X
軸上水平位移 100px
再繞著 Y
軸順時針轉(zhuǎn) 60
度,和先繞 Y
軸順時針轉(zhuǎn) 60
度,再在 X
軸上頭水平位移 100px
的結(jié)果會完全不同,因為當(dāng)我先繞了 Y
軸轉(zhuǎn)動,整個 X
軸也會跟著轉(zhuǎn)動,這時候再做水平位移,位置就會像是在深度做變換。
.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
的數(shù)量少還比較看不出來,當(dāng)今天 transform
里頭數(shù)量一多,造成的差異就更加明顯,這也是在玩 CSS 3D 最最最最最需要注意的重點所在,一定要注意,一定要注意,一定要注意,非常重要所以再說三次呀!
.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 的原理解析,坦白說如果明白了 3D 的結(jié)構(gòu)組成,CSS 的 3D 就沒有難度,總而言之,就是先建立好三個元素:攝影機、立體空間、立體物件,就可以開始玩轉(zhuǎn) CSS 3D 啰!
本文轉(zhuǎn)載于@oxxo的玩轉(zhuǎn)CSS 3D系列教程第一篇:http://www.oxxostudio.tw/articles/201506/css-3d.html