無立體,不動畫,CSS3 3D 動畫屬性入門

關於CSS3 3D Transform是變形屬性裏面的戰鬥機,就像立體幾何的學習要在平面幾何以後相似,在關於全部的2D的屬性摸個七七八八以後,終於開始進階3D變形了。先來一張SVG的背景圖。炎炎夏日,清涼一下,即便不能行萬里路,至少還有心在遠方。 算法

對於2D方向的移動,已經乏善可陳了,一個transform:translateX() 或者transform:translateY() 就能輕鬆實現水平和垂直方向的移動。那咱們都知道,3D空間多了一個Y軸維度,4D空間多了一個時間維度,5D空間多了……就此打住,本篇不討論科幻。(此處插播一本小說《平面國》,2D維度的世界,也比較有趣。)言歸正傳,顯示屏展示了二維平面,那把Z軸想象成你和顯示屏之間的一個距離軸線。既然如此,那transform:translateZ()是否是就能實現Z軸維度的移動了呢?你想多了。畢竟從2D到3D也是一個量變,豈能辣麼簡單? 瀏覽器

1.關於容器和透視屬性

先簡單來講一下瀏覽器實現3D效果的原理,各類座標軸什麼的就不班門弄斧了,畢竟一搜一大堆。SVG向瀏覽器宣告「我要使用3D效果啦,作好準備」就要傳遞一個信號,只有translateZ是不夠的,瀏覽器須要有一個準則,就是沿Z軸移動的比例是什麼?換句話說,須要設置一個透視點perspective來配置3D空間,也就是CSS的perspective屬性,再直白點說,就是咱們的眼睛距離屏幕(Z軸)的距離。那perspective屬性應該對誰定義呢?舞臺,或者說是SVG的父容器。好比說,我定義了沿Z軸移動的動畫cubic以下:bash

@keyframes cubic{
0% {transform: translateZ(0)}
100% {transform: translateZ(-300px)}
}
.cubic {animation:cubic 2s ease;}複製代碼

做爲圖片而存在的SVG是沒有perspective屬性的,它的父容器是什麼?咱們都知道,SVG裏面的標籤,<path>也好,<circle>也好,都是一些繪製方法,<g>也只是進行了組合,並不是真正的父容器,這時,純SVG有些無力了,那咱們就把它放到一個<div>裏,來實現這種3D效果。既然「在我地盤這兒那就得聽個人」,下面就來定義這個霸氣的地盤(或者稱之爲舞臺)透視屬性。svg

.stage {
perspective: 200px; 
background:#e5fffb; /*給舞臺定義一個淺綠背景色*/
}複製代碼

<body>代碼部分就簡單多了,只須要<div>裏嵌套這個<SVG>就OK了。學習

<div class="stage">
<svg class="cubic" xmlns="http://www.w3.org/2000/svg" width="800" height="600">
<g>
…此處省略若干組成SVG圖形的代碼
</g>
</svg>
</div>複製代碼

來檢驗一下效果如何動畫

是否是有些失望?這明明就是縮放效果好不啦?我要你?明明一個transform:scale()就能搞定!掀桌子,抗議,停停停,說過Z軸是眼睛和屏幕間的軸線,沿Z軸移動可不就是縮放嘛。人家但是用二維的表現來營造觀察者離屏幕移動的的場景啊(你還想怎樣,難不成讓圖片從屏幕裏出來,像貞子同樣?)。 spa

2.透視屬性與變化

這裏關於perspective屬性值咱們先定義幾個極值看一下,第一個,我定義perspective:1000px,效果以下:3d


在一樣translateZ狀況下,感受變化很小。

第二個,我定義perspective:1px,效果以下:code


在一樣translateZ狀況下,變化灰常劇烈,縮成了一個點。

爲了好理解,咱們先假定地心說,宇宙萬物繞着地球轉。請看下圖(原諒我不會3D建模,好憂桑)orm


左邊那個場景咱們想象成一個小人以45度角仰望天空,一輪明月懸空高掛,右邊那個場景咱們想象成一個小人頭上不遠的地方掛了個大南瓜吧。在視覺上,明月和南瓜是同樣大小的。此時,當太陽向小人方向移動2米,小人徹底看不到這種移動,但南瓜往腦殼方向移動2米,只見愈來愈大,個人媽呀,這是要砸下來了。因此一樣的移動距離,因爲視距不一樣,產生了差別。正所謂近大遠小,也就是說 perspective值越大,表明觀察者離屏幕越遠,那一樣 translateZ的移動距離,在視覺上呈現的效果越明顯。

由於我把translateZ定義成了負值,就是背離眼睛方向(眼睛→屏幕),因此愈來愈小,那當我改一下,transform: translateZ(300px),讓Z軸移動爲背離屏幕狀況下又是怎樣的呢?


噴薄欲出,這就是南瓜砸腦殼的效果吧。

再延伸一下,當perspective爲0時,會是什麼效果呢,沿Z軸正向移動時,大到無極限,沿Z軸負向移動時,小到看不見?不,此極值至關於眼睛貼到了屏幕上,恭喜你,這是進入了二維世界,因此Z軸的移動對於二維平面來講,是沒有變化的。這也就是爲何咱們perspective不定義(默認爲0)時,沒有效果的緣由。

3.關於透視原點perspective-origin

全部的變形動畫都有一個原點(不定義,不表明沒有,一般是默認值),這在tranform:rotate選擇動畫中表現最爲明顯,咱們會常常定義變形原點tranform-origin來肯定元素動畫效果的基準點。對於咱們3D動畫屬性來講,就要增長一個相似的概念,透視原點perspective-origin。若是說perspective值表明眼睛離屏幕的垂直距離,那perspective-origin則表明了上下左右晃動腦殼後再去觀察,此動做是二維平面的動做,所以perspective-origin屬性包括兩個值,一個與水平X相關,一個與垂直y相關當缺省時,默認爲(center center)仍是上面的Z軸移動效果,來試一下改變perspective-origin屬性值會發生什麼。以下,我給父容器增長一個透視原點的屬性值

.stage {
perspective: 200px; 
background:#e5fffb; 
perspective-origin: left  top; 
}複製代碼

沿Z軸移動就變成了下面這個樣子:


其餘屬性值就再也不一一嘗試了,大概也能猜個七七八八,這裏除了left right top bottom center這種直接寫法,還支持百分比的表示方法。感興趣能夠自行嘗試。

4. 3D旋轉動畫

沿Z軸移動這種效果,別說衆位看官沒有興趣,我也覺索然無味,單純的移動能夠靠2D的一些屬性來完成,接下來試個稍微有趣點的效果,3D空間的旋轉。在2D平面上的旋轉transform:rotate(),是點旋轉,這裏的點,是指在平面上繞的點,而3D空間的旋轉,則是軸旋轉。繞X軸或Y軸,因此咱們要把屬性寫成transform:rotateX()或transform:rotateY()這樣子。
如今從新定義一下動畫屬性,先來個繞X軸旋轉45度:

.cubic {animation:cubic 2s ease}
@keyframes cubic{
0% {transform: rotateX(0)}
100% {transform: rotateX(45deg)}
}複製代碼

獲得的動畫效果:

從效果裏能夠明顯的看出,首先,旋轉方向的定義,正值是向屏幕內部旋轉,若是這麼說沒有空間感的話,也能夠理解成在Y和Z組成的平面(即與X軸垂直的平面)以笛卡爾座標系X軸正值方向觀察爲順時針旋轉。算了,太彆扭了,仍是來張3D座標系的圖解釋一下。

從動畫效果裏咱們會發現一個奇怪的現象,就是SVG底圖——變!虛!了!說好的矢量圖形無限放大呢?由於不懂算法渲染什麼的,我的猜想瀏覽器在處理這類3D效果時,先繪製了一張位圖,而後以位圖爲藍本進行處理,好吧,我在胡扯,具體緣由等查到相關資料再更正。

改幾個角度看一下,先改爲-90deg,效果以下:

再來個180度翻轉的:

以及360度繞軸一圈的(先打住,沒意思了啊,猜都猜出效果了),這裏呢,關於透視原點perspective-origin由於沒作定義,因此旋轉的中規中舉,我隨便改一下,把父容器的透視原點屬性值改爲perspective-origin: right bottom,也就是右下角,獲得的效果是下面這樣的:

繞完X軸的看過一遍以後,繞Y軸的閉着眼就能想象。隨便來一個吧,如今我把繞Y軸的角度定義成120度

@keyframes cubic{
0% {transform: rotateY(0)}
100% {transform: rotateY(120deg)}
}複製代碼

有沒有興趣看看繞Z軸好比transform: rotateY(120deg)的效果:


其實想一想也是了,對於2D平面的圖形,Z軸就是一個點,因此繞Z軸旋轉就變成了普通的旋轉動畫效果。

仍是3D的玩起來更是花樣百出。興趣指數,五顆星!

3D動畫一旦玩起來,是很可怕的,前面雖然各類屬性設置來過一遍,但說到底,咱們用的SVG底圖仍是2D的,一張平面的圖轉來繞去的能有什麼意思?總歸是缺少3D應有的使用場景。運用在多面體上的方法和效果下次再更。

相關文章
相關標籤/搜索