好吧,CSS3 3D transform變換,不過如此!

by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=2592css

1、寫在前面的秋褲

早在去年的去年,我就大肆介紹了2D transform相關內容。看過海賊王的都知道,帶D的傢伙都不是好惹的,2D我輩尚能夠應付,3D的話,呵呵,估計我等早就在千里以外被其霸氣震暈了~~html

看看下圖女帝的動做以及神情,就能夠知道名字帶D的傢伙的厲害!
路飛女帝D族的厲害 張鑫旭-鑫空間-鑫生活css3

最近折騰iPad的一些東西,有一些3D效果的交互。有些事情,總覺得是遙遠的將來,誰知真正發生的時候說來就來,好比說一顆想結婚的心,又比方說在實際項目中折騰3D transform效果。web

哭泣鑫表情 張鑫旭-鑫空間-鑫生活

然而,雖然之前折騰過3D變換效果(webkit),但都是依葫蘆畫瓢,囫圇吞棗,真正要輕鬆實現想要的3D效果,是須要深刻理解的,因而,此時的本身苦逼了,淚奔ing……瀏覽器

木有辦法,找資料,本身思考學習唄,當我看到下面這張基本圖的時候,個人右側的濃眉毛情不自禁抖動了兩下,呵,呵呵~~
3D變換座標圖解 張鑫旭-鑫空間-鑫生活ide

這個長得像原子核同樣的是什麼東東?那像章魚哥同樣四處橫生的箭頭好嚇人哦!後面怎麼還有一個蒼蠅拍?? CSS好可怕,我要回去找媽媽……wordpress

想必大部分的同行應該跟我同樣,沒有愛因斯坦爺爺的智商,沒有上鏡須要把表摘掉的爸爸。所以,那些術語連篇的CSS3 3D transform介紹的資料過於耀眼,沒法直視。怎麼辦?佈局

好吧,佛家有云,我不入地獄誰入地獄。這裏,我就從凡人們的視角說說CSS3 3D transform的一些東西,但願說的東西比較親民,不要嚇着你們。學習

2、首先,情感化認識

我以爲吧,要想理解一個東西,最好先有一些感性的認識。動畫

CSS3中的3D變換效果,本質上就是咱們OOXX時候各類姿式的變換,又稱各類體位的變換。

雖然都是成年人,但考慮到仍有很多窩中待守的雛鳥,若是上面的解釋想不過來,就想一想如下這些:
1. 下圖的這些人在幹嗎?

跳水?NO, No, No!! 記住,他們不是在跳水,是在作3D變換!!!

2. 下圖可愛baby在幹嗎

廣播體操?NO, No, No!! 記住,他不是在作操,是在作3D變換!!!

3. 來到2次元,下圖這個妹子在這幅姿態稱爲:
鑫表情 性感 色
賣萌?NO, No, No!! 記住,他不是在賣萌,是在作3D變換!!!

哈哈哈哈,是否意識到:在顯示世界中,一切的動做(包括上面巨乳萌妹所引起的精蟲上腦),都是屬於3D transform變換。 所以,要學習與理解3D transform變換很簡單,一句話,到現實世界找個東西映射一下便可。

3、認識的突破口:rotateX, rotateY, rotateZ

3D transform中有下面這三個方法:

  • rotateX( angle )
  • rotateY( angle )
  • rotateZ( angle )

理解了這三個方法,後面更難懂的perspective就好下手了,能夠說是突破口!

rotate旋轉的意思,rotateX旋轉X軸,rotateY旋轉Y軸,rotateZ旋轉Z軸……

什麼X軸/Y軸/Z軸,這幾個詞從我嘴裏一出來,別說大家,我本身都暈了~~

趕快,從現實世界找對應東西理解(參照下面人的旋轉):
鄒凱的體操單槓運動是rotateX
單槓

蔡依林姐姐的鋼管舞是rotateY
蔡依林-鋼管舞 張鑫旭-鑫空間-鑫生活

旋轉飛刀的特技表演是rotateZ
飛刀魔術

仍是理解不過來?好吧,假設你是男的,以你的女友舉例,假如本來你和她面對面站着,而後你——
從正面將其推到就是rotateX
妹子推到與transform rotateX 張鑫旭-鑫空間-鑫生活

讓其原地轉個90度欣賞其側面的豐滿曲線就是rotateY
妹子推到與transform rotateY 張鑫旭-鑫空間-鑫生活

把妹子抱到牀上側面躺着就是rotateZ
妹子推到與transform rotateZ 張鑫旭-鑫空間-鑫生活

因而,下面CSS世界中的簡單3D效果是否是更容易理解了呢?!
transform rotateX(45deg)的效果圖 張鑫旭-鑫空間-鑫生活 transform rotateY(45deg)的效果圖 張鑫旭-鑫空間-鑫生活 transform rotateZ(45deg)的效果圖 張鑫旭-鑫空間-鑫生活

//zxx: 下面爲廣告~~注意不要勿點~~嘻嘻~~

4、必不可少的perspective屬性

perspective的中文意思是:透視,視角!

perspective屬性的存在與否決定了你所看到的是2次元的仍是3次元的,也就是是2D transform仍是3D transform. 這不難理解,沒有透視,不成3D.

咱們初中學美術,或者學建築的同窗確定接觸過透視的一些東西:
3D透視 張鑫旭-鑫空間-鑫生活 3D透視 張鑫旭-鑫空間-鑫生活

不過,CSS3 3D transform中的透視的透視點與上面兩張示例圖是不一樣的:CSS3 3D transform的透視點是在瀏覽器的前方

或者這麼理解吧:顯示器中3D效果元素的透視點在顯示器的上方(不是後面),近似就是咱們眼睛所在方位!

比方說,一個1680像素寬的顯示器中有張美女圖片,應用了3D transform,同時,該元素或該元素父輩元素設置的perspective大小爲2000像素。則這張美女多呈現的3D效果就跟你本人在1.2個顯示器寬度的地方(1680*1.2≈2000)看到的真實效果一致!!
1680寬度像素顯示器與3D transform視角大小示意 張鑫旭-鑫空間-鑫生活

5、translateZ幫你尋找透視位置

若是說rotateX/rotateY/rotateZ能夠幫助理解三維座標,則translateZ則能夠幫你理解透視位置。

咱們都知道近大遠小的道理,對於沒有rotateX以及rotateY的元素,translateZ的功能就是讓元素在本身的眼前或近或遠。比方說,咱們設置元素perspective爲201像素,以下:

perspective: 201px;

則其子元素,設置的translateZ值越小,則子元素大小越小(由於元素遠去,咱們眼睛看到的就會變小);translateZ值越大,該元素也會愈來愈大,當translateZ值很是接近201像素,可是不超過201像素的時候(如200像素),該元素的大小就會撐滿整個屏幕(若是父輩元素沒有相似overflow:hidden的限制的話)。由於這個時候,子元素正好移到了你的眼睛前面,所謂「一葉蔽目,不見泰山」,就是這麼回事。當translateZ值再變大,超過201像素的時候,該元素看不見了——這很好理解:咱們是看不見眼睛後面的東西的!

再生動的文字描述也不如一個實例來得直觀,您能夠狠狠地點擊這裏:translateZ方法輔助理解perspective視角demo

建議Chrome瀏覽器下訪問,可使用range控件,演示效果更贊,以下截圖:-100時候最小,200時候超級滿屏(垂直方向因特殊佈局限制沒有顯示),250的時候由於元素已經在視點以外,所以是一片空白(看不見)。
translateZ -100像素最遠距離最小顯示 張鑫旭-鑫空間-鑫生活 translateZ 200像素時候超級大的顯示 translateZ爲250像素時候元素在視區以外,所以看不見是空白 張鑫旭-鑫空間-鑫生活

6、perspective屬性的兩種書寫

perspective屬性有兩種書寫形式,一種用在舞臺元素上(動畫元素們的共同父輩元素);第二種就是用在當前動畫元素上,與transform的其餘屬性寫在一塊兒。以下代碼示例:

.stage {
    perspective: 600px;
}

以及:

#stage .box {
    transform: perspective(600px) rotateY(45deg);
}

您能夠狠狠地點擊這裏:perspective屬性的兩種書寫demo

結果以下縮略圖:
CSS3 transform perspective兩種書寫形式demo效果截圖

從上圖咱們貌似能夠看到,雖然書寫的形式,屬性名稱不一致,可是,效果貌似是同樣的~~果然是這樣嗎???

實際上否則,上面的demo上下兩個效果之因此會同樣,是由於舞臺上只有一個元素,所以,發生了巧合,其正好表現同樣了。若是,若是舞臺上有不少個元素,則兩種書寫形式的表現差別就會立馬顯示出來了!

您能夠狠狠地點擊這裏:舞臺多元素下的perspective兩種書寫對比demo

demo頁面效果縮略圖以下(因背景色隨機,可能與下圖有差別):
不一樣transform perspective書寫下的表現差別

好吧,圖中的效果其實不難理解。上面舞臺整個做爲透視元素,所以,顯然,咱們看到的每一個子元素的形體都是不同的;而下面,每一個元素都有一個本身的視點,所以,顯然,由於rotateY的角度是同樣的,所以,看上去的效果也就如出一轍了!

關於Chrome瀏覽器以及透視盲區
在Chrome瀏覽器下,要想看到完整的3D效果,還須要3D變換元素正好在窗體的垂直居中位置,所以,在Chrome瀏覽器下,生成了兩個位置居中的按鈕,幫助您看到想要的效果:
Chrome瀏覽器下位置居中按鈕 張鑫旭-鑫空間-鑫生活
Chrome瀏覽器下舞臺垂直居中3D效果顯示

當咱們改變第一個range控件值爲200的時候,您會發現右側第三個元素看不見了:
200值的時候有元素看不見

這不難理解,前面一排門,每一個門都是1米,你距離門2米,顯示,當全部門都開了45°角的時候,此時,距離中間門右側的第二個門正好與你的視線平行,這個門的門面顯然就什麼也看不到。這就是爲何上面右側第三個門一片空白的元素——特定的視角以及距離造成的視覺盲區。

7、理解perspective-origin

perspective-origin這個屬性超級好理解,表示你那雙色迷迷的眼睛看的位置。默認就是所看舞臺或元素的中心。有時候,咱們對中心的位置是不感興趣的,但願視線放在其餘一些地方。比方說
不一樣視線落地位置對應不一樣的perspective-origin值

一圖勝千言,屌絲男們這個應該都懂的。

下面爲立方體的實際應用透視效果圖:

perspective-origin: 25% 75%;

立方體不一樣透視角度的效果 張鑫旭-鑫空間-鑫生活

8、transform-style: preserve-3d

transform-style屬性也是3D效果中常用的,其兩個參數,flat|preserve-3d. 前者flat爲默認值,表示平面的;後者preserve-3d表示3D透視。

preserve-3d符合咱們真實世界的思惟認識。比方說,你讓妹子右轉了45度,此時妹子腦殼左轉45度想你吐舌賣萌,妹子的臉蛋應該和你是面對面平行的。
妹子推到與transform rotateY 張鑫旭-鑫空間-鑫生活
應用transform-style: preserve-3d聲明的元素確實是這樣表現的,可是,若是使用默認的flat值,其效果表現——恕我想象力有限——想不通:妹子的臉仍是左轉45度的,同時腦殼彷佛移到了身體之外的地方

所以,基本上,咱們想要根據現實經驗實現一些3D效果的時候,transform-style: preserve-3d是少不了的。通常而言,該聲明應用在3D變換的兄弟元素們的父元素上,也就是舞臺元素。

9、backface-visibility

在顯示世界中,咱們沒法穿過軟妹A看到其身後的軟妹B或C或D;可是,在CSS3的3D世界中,默認狀況下,咱們是能夠看到背後的元素(也不知可不能夠透視妹子的衣服~)!
看不到後面的軟妹,哦呵呵, backface-visibility, 張鑫旭-鑫空間-鑫生活

所以,爲了切合實際,咱們經常會這樣設置,使後面元素不可見:

backface-visibility:hidden;

10、實際應用-圖片的旋轉木馬效果

您能夠狠狠地點擊這裏:圖片的旋轉木馬效果demo

建議在足夠新版本的FireFox瀏覽器或Safari瀏覽器下觀看,Chrome可能須要居中定位查看,下圖爲效果縮略圖:
圖片3D旋轉木馬效果截圖 張鑫旭-鑫空間-鑫生活

原理:
那些看上去很酷酷的CSS3 3D效果其實就顛來倒去那幾個屬性(本文提到的這幾個),折騰來折騰去,這裏這個效果顯然也是如此。

首先HTML結構,以下:

舞臺
    容器
        圖片
        圖片
        圖片
        ...

對於舞臺,很簡單,加個視距,比方說800像素:

perspective: 800px;

對於容器,很簡單,加個3D視圖聲明,以下:

transform-style: preserve-3d;

而後就是圖片們了。爲了避免至於產生相似DNA的螺旋狀效果,咱們讓全部圖片position:absolute,公用同一個中心點。

顯然,圖片旋轉木馬是相似鋼管舞旋轉的運動,所以,咱們關心的是rotateY的大小。

由於要正好繞成一個圈,所以,圖片rotateY值正好0~360等分,因而,若是有9張圖片,則每一個圖片的旋轉角度累加40(360 / 9 = 40)度便可。所以有:

img:nth-child(1) { transform: rotateY(   0deg ); }
img:nth-child(2) { transform: rotateY(  40deg ); }
img:nth-child(3) { transform: rotateY(  80deg ); }
img:nth-child(4) { transform: rotateY( 120deg ); }
img:nth-child(5) { transform: rotateY( 160deg ); }
img:nth-child(6) { transform: rotateY( 200deg ); }
img:nth-child(7) { transform: rotateY( 240deg ); }
img:nth-child(8) { transform: rotateY( 280deg ); }
img:nth-child(9) { transform: rotateY( 320deg ); }

這樣就行了嗎?

No, No, No!!!

想一想看那,雖然9個絕色美女每一個人的方位不同,但都站在同一個點上,早就擠做一團,A罩都擠成C了,顯然是不行的(見下圖只設置rotateY)!咱們須要拉開空間~~

只設置rotateY時候,衆多美女圖片擠做一團

如何拉開空間,很簡單。

想一想看那:9個美女,分別面朝東南西北共9個不一樣方位,她們只要每一個人向前走個4~5步,美女們之間的空間不久拉開了,呈現圓形了!想象一下夜空中,禮花綻放的場景~~

這裏的向前走4~5步,聰明的人應該已經知道了,就是本文提到的translateZ, 當translateZ爲正值的時候,元素會向其面對的方向走去;若是元素無旋轉,就會朝顯示器走來!!

如今只剩下一個問題了,美女們要向前走多遠呢??

這個距離是有計算公式滴!

拿本demo距離,每張美女圖片的寬度是128像素,所以,有以下理想方位效果圖:
旋轉木馬效果理想方位圖 張鑫旭-鑫空間-鑫生活

上圖中紅色標註的r就是的demo頁面中圖片要translateZ的理想值(該值可讓全部圖片無縫圍成一個圓)!

r的計算很簡單,有初中數學水平的人應該都會:

r = 64 / Math.tan(20 / 180 * Math.PI) ≈ 175.8

demo頁面爲了好看,圖片之間留了點間距,使用的translateZ的值爲175.8 + 20 = 195.8.
旋轉木馬demo頁面translateZ值大小

最後的最後,要讓木馬旋轉起來,只要讓容器每次旋轉40度就能夠了。

節省篇幅,具體的JavaScript操做代碼就不展現了,您有興趣能夠查看demo頁面源代碼。

理解了旋轉木馬3D效果實現原理,基本上,其餘些3D效果能夠輕鬆駕馭了,所以,本效果仍是值得你花功夫看看滴~~

11、好吧,結語

理論上,現實世界,及3次元世界中的各類有規律的運動效果均可以使用CSS3 transform 3D方法實現。文章最後的旋轉木馬效果能夠說是各種千奇百怪效果中的滄海一粟~~其餘各種有的沒有的效果就靠你的大腦就構想了。至於實現嘛,理解了,也就 都是小菜。可是,要是不理解,純粹從網上copy些效果代碼,那永遠就是copy的命咯!

文章篇幅已經很長了,個人指頭也敲出老繭來了,就再也不囉嗦什麼了。但願本文的嗑叨、賣弄、折騰可以讓您學習CSS3 3D transform變換的相關東西更加輕鬆點!

行文倉促,文中有錯誤在所不免,歡迎諸位指正。最後,感謝閱讀,共同進步!

原創文章,轉載請註明來自張鑫旭-鑫空間-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=2592

相關文章
相關標籤/搜索