CSS3的癲瘋展示——3D立方體動畫(你要的全景檢視來了)

泱泱發表於2017-08-16

上篇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能做哪些炸裂的效果。等更新。

相關文章