CSS3的 3D立方體旋轉動畫

今次就來個大家用3D屬性最愛炫技的場景,旋轉的立方體,有人聲稱這種動畫簡直代表了CSS3的癲瘋,不不,是巔峰。做完之后只想吼一聲,你說的沒差!由平面動效進階到立體動效真是……立方體六個面要做足足六種不同的設置,所以那些玩八面體,十二面體,……等等的,大寫的“服”字。其他人做的立方體3D動畫,看了幾個,差不多都是<div>實現的,嗯哼,我用<SVG>來做一下吧,至于原因嘛,后面揭曉,當然,如果失敗的話,此句請自動忽略。

1. 先立起來

不可避免的,要先來個基礎圖形。錯錯錯,是基礎物體,反正就是個需要立體的東西,隨便怎么稱呼。基本上有兩種方法可以實現,先來一種直觀好理解的。

看上面這張圖,我把立方體的六個面平鋪開,右上角的那個是后面。此時,假設立方體是在視線正前方,好了,面有了,現在需要把它們折疊起來,像折紙盒一樣,組成一個立方體。先看一下dom結構。

<div class="stage">
<div class="content">
<svg   id="cubic1" xmlns="http://www.w3.org/2000/svg" >
<rect   height="200" width="200" />
</svg>
<svg   id="cubic2" xmlns="http://www.w3.org/2000/svg" >
<rect   height="200" width="200" />
</svg>
<svg   id="cubic3" xmlns="http://www.w3.org/2000/svg" >
<rect   height="200" width="200" />
</svg>
<svg   id="cubic4" xmlns="http://www.w3.org/2000/svg" >
<rect   height="200" width="200" />
</svg>
<svg   id="cubic5" xmlns="http://www.w3.org/2000/svg" >
<rect   height="200" width="200" />
</svg>
<svg   id="cubic6" xmlns="http://www.w3.org/2000/svg" >
<rect   height="200" width="200" />
</svg>
</div>
</div>

非常簡單,我定義了兩個容器,一個是舞臺stage,一個是包裹立方體的content,content里是6個SVG,每個SVG只有一個簡單的矩形rect。我的目的是讓content在stage里進行3D動效變化。

CSS定義如下:

.stage {width: 800px; height: 600px; background:#e5fffb; perspective:1000px;}
.content{transform-style: preserve-3d}
#cubic1{fill:#f29a76}
#cubic2{fill:#61BFBE}
#cubic3{fill:#BADDD6}
#cubic4{fill:#FFB5BA}
#cubic5{fill:#866667}
#cubic6{fill:#E25D6E}
SVG {position: absolute;top:200px; left:300px;width:200px; height:300px}

6個SVG都是寬200,高200,雖然里面的矩形<rect>也都是相同尺寸,卻沒有進行統一的定義,是因為想嘗試后期給每個SVG定義不同的動畫屬性。容器的擺放關系如下圖:

目前,通過position屬性的設置,六個面是重疊在一起的,因此,在折疊之前,先把每個方塊挪到自己對應的位置。移動的CSS屬性就很簡單了。根據圖示,cubic1,也就是正對著我們的面,不需要移動,其他增加transform: translate相應的屬性設置,定義如下:

#cubic2{fill:#61BFBE;transform: translateZ(-200px)} /*后面遠離屏幕200px移動*/
#cubic3{fill:#BADDD6;transform: translateY(-200px)} /*上面垂直向上200px*/
#cubic4{fill:#FFB5BA;transform: translateX(200px)} /*右面水平向右200px*/
#cubic5{fill:#866667;transform: translateY(200px)} /*下面垂直向下200px*/
#cubic6{fill:#E25D6E;transform: translateX(-200px)} /*左面水平向左200px*/

移動之后的效果是下面這種(閑著也是閑著,我把移動過程做了動效):


好了,現在各在其位,下面要各司其職,進行折疊了。


這里有一點要說明,就是移動過之后,關于坐標系的變化,拿其中一個面cubic4為例來說,當發生水平向右移動200px后,此時坐標系也會發生變化同樣的位移,因此在做折疊(旋轉)90度的3D變形時,旋轉的基軸雖然在原坐標系是右邊的垂直軸,但對于移動后的坐標系,變成了左邊的垂直軸,因此,對應的變形原點的設置為transform-origin: center left。舉一反五,其他的幾個就不一一細說了,直接放上增加3D旋轉后的CSS3屬性(cubic2僅僅發生了Z軸方向的位移,沒有旋轉動畫,所以無需設置)。

#cubic3{fill:#BADDD6;transform: translateY(-200px) rotateX(90deg) ;transform-origin: bottom center;}
#cubic4{fill:#FFB5BA;transform: translateX(200px) rotateY(90deg);transform-origin: center left;}
#cubic5{fill:#866667;transform: translateY(200px)  rotateX(-90deg);transform-origin:top center;}
#cubic6{fill:#E25D6E;transform: translateX(-200px) rotateY(-90deg);transform-origin: center right;}

完成之后,效果是下面這種:

(這特么是不是在逗我,就一個平面非說是個立方體……!)別急,就知道你會這樣說,所以我用動效展示一下這個過程:

此處應有動畫!!應有動畫!!應有動畫!!(我忘記錄屏了,天雷滾滾)

這下信了吧?其實這貨就是個立方體,貨真價實,只不過我們沒有給最外層的容器(也就是3D變形的舞臺)設置透視點位置,默認是屏幕正前方,所以你只看到了一面。來來來,我把透明度調整一下,再改改透視原點的位置,效果是下面這種。喲,立方體出來了。


上面說過,關于立方體的組成有兩個方法,我們第一種是用了先平移后折疊,那第二種就是先折疊后平移了。說到這里,可能會不解,無所謂了管它呢,有甚區別,我自己做的過程中感覺差別還蠻大,下面這種方法要求對空間的理解能力更強,但代碼卻優化了很多,省去一干transform-origion的設置。在上面的組合立方體的過程中,我們把面向自己的那一面作為了二維的基面,其他方形都是基于此進行了變換,也就是說最后組成的立方體從三維角度來說,是向背離屏幕的Z軸進行延伸的(代表背面的cubic2進行了Z軸負向的位移)。
這次,我們假定組成后的立方體的中心就是坐標系的原點,首先,我仍然是用絕對定位法把所有的組成面都固定到容器統一的位置,只進行位移的正面和背面不用管,先來進行3D方向的旋轉。依舊用動畫表示吧。這里為了能看到效果,我把舞臺stage的透視原點定義為偏右下方perspective-origin:80% 80%


動畫效果有了,只是由于透視點的方向問題,結果似乎少了兩個面,再把透視點改成偏左上perspective-origin:20% 20%看一下:


完成第一步的旋轉,下面就是要進行全體位移了,那么重點來了。
以左面cubic6為例,如下圖所示:


在進行3D旋轉變形后,坐標系也相應的做了旋轉變形,從視覺角度來看,做完選擇變形后的cubic6要進行向左移動100px的水平位移,但由于坐標系變形的緣故,對于其本身旋轉后的坐標系而言,此時水平方向變成了Z軸,因此水平位移也就變成了translateZ。 把第二種方法形成立方體的動畫看一下:

方法二之所以更優化,是因為關于六個cubic的定義簡化如下:

#cubic1{fill:#f29a76;transform:translateZ(100px);}
#cubic2{fill:#61BFBE;transform:translateZ(-100px);}
#cubic3{fill:#BADDD6;transform:rotateX(90deg) translateZ(-100px)}
#cubic4{fill:#FFB5BA;transform:rotateY(-90deg) translateZ(100px)}
#cubic5{fill:#866667;transform:rotateX(-90deg)translateZ(-100px)}
#cubic6{fill:#E25D6E;transform: rotateY(90deg) translateZ(100px)}

2. 再轉起來

基礎部件已經搭起來了,下面就讓這個立方體動起來。說立方體不好理解,但我們在做的時候把它放到了一個content<div>容器里,因此,讓這個容器做一些變換就可以了。至于用哪種方法得到的立方體,此處隨意,我用了二。先來個最簡單的繞Y軸旋轉的,CSS部分如下:

@keyframes content{
to{transform: rotateY(360deg)translateZ(20px)}
}
.content{transform-style: preserve-3d; animation:content 2s linear both infinite; }

效果:

寫到這里暫時停一下,剩下的放到另一篇吧,我要好好想一下關于3D能做哪些炸裂的效果。等更新。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容

  • 把立方體的盒子搭出來之后,因為怕文章又臭又長(嗯,就是沒有想好玩什么效果,偏不告訴你)關于動效沒有做更多的處理,只...
    泱泱悲秋閱讀 2,077評論 1 8
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,579評論 25 707
  • 1、屬性選擇器:id選擇器 # 通過id 來選擇類名選擇器 . 通過類名來選擇屬性選擇器 ...
    Yuann閱讀 1,650評論 0 7
  • 以前覺得23歲就是最好的年齡了。青春,張揚,可以肆意揮灑自己的精力。熬一個通宵后睡一覺立馬精神煥發。尤其生了哥哥以...
    景一夫閱讀 380評論 0 0
  • 一 寶貝最近幾天,張開眼睛,看到什么,都要指著問:“這是啥?”“這是啥?”告訴她了還是接著問“這是啥?”,全家人都...
    棒棒糖讀寫筆記閱讀 784評論 3 3