CSS 3D變形動畫屬性 之逆天立方體疊加動畫

泱泱發表於2017-08-22

上一篇,
juejin.im/post/5993d9…
把立方體的盒子搭出來之後,因為怕文章又臭又長(嗯,就是沒有想好玩什麼效果,偏不告訴你)關於動效沒有做更多的處理,只做了一個繞Y軸旋轉,這篇試著做幾個效果,CSS3 3D變形的坑太大,一時半會的也填不滿,先探探路。
燃鵝,這種跑死瀏覽器的3D動效實際用處不多,各位看看就好,我也僅僅是有興趣鵝已。

1. 輕鬆改變各種效果

為了讓3D動效發揮最大程度的頭暈眼花,我在搭立方體的時候特意用了<SVG>作為組成各個面的圖形元素,如果用<div>的話,誠然,可以利用CSS3的一些屬性來實現一些漸變、描邊、方格等等效果,但靈活性與<SVG>不能比。比如,我先來個立體框的效果。為了讓舞臺更大一些,我重新做了定義,所以依舊放上dom結構。
具體的各個面組成元素就不再一一解釋了,可以看上篇。總之就是6個<SVG>組成了6個面,現在這個案例裡,我用的是最基礎的,六個矩形<rect>

<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>複製程式碼

CSS部分如下,我重新優化了一下,便於動效的設定。

.stage {
width: 1000px; height: 1000px;   
/*更大的舞臺*/
background:#e5fffb;
perspective:1000px;             
/*透視原點定義的比較大是讓立方體儘可能不變形*/
}

@keyframes content{
to {transform:rotateX(360deg) rotateY(360deg);} 
}                                 
/*定義一個繞X軸和Y軸同時360度旋轉的動畫*/

.content{
transform-style: preserve-3d; 
animation:content 3s linear both  infinite ;
position: absolute;top:400px; left:400px;
width:200px; height:200px
}

#cubic1{transform:translateZ(100px);}
#cubic2{transform:translateZ(-100px);}
#cubic3{transform:rotateX(90deg) translateZ(-100px)}
#cubic4{transform:rotateY(-90deg) translateZ(100px)}
#cubic5{transform:rotateX(-90deg)translateZ(-100px);}
#cubic6{transform: rotateY(90deg) translateZ(100px);}
rect{fill:none; stroke-width:3; stroke:#f29a76}
SVG {opacity:1;position: absolute;width:200px; height:200px}複製程式碼

現在動畫效果是下面這種:


關於旋轉的容器content我並沒有給予transform-origin即旋轉基點的定義,對於三維動畫而言,transform-origin(x y z)最多可以定義三個值,X軸、Y軸和Z軸的偏移值,預設值為(50% 50% 0),也就是容器的中心點。 因為這裡面涉及到兩個原點,透視原點和變形原點,所以一定要搞清楚各自的歸屬,透視原點是舞臺stage的屬性,這個決定了立方體的表現形式,而變形原點則是執行變形動畫的元素的屬性,這個決定了立方體的運動形式。
比如說如果我改變transform-origin的值,就可以得到下面這種動畫:


立方體的運動軌跡發生變化,立方體的表現形式是不變的。

而改變透視原點的效果則是下面這種:


與上面的正好相反,立方體的運動軌跡不變,但表現形式發生了變化。

好了,拿那個繞著自己的中心點旋轉的規規矩矩的立方體作為基礎模板,玩一些疊加的動效。首先弄清楚一點,目前進行3D旋轉的是我們定義為content,也就是包含了六個<SVG><div>,而<SVG>本身,還沒有發揮自己的特長呢。以前做過很多<SVG>的動效,現在疊加幾個試試,看能不能讓系統崩潰(o(╥﹏╥)o)。

2. 兩個套在一起的立方體

嚴格來說,這只是個效果,並沒有發揮上面囉囉嗦嗦半天強調的<SVG>的靈活性。但這也是靈光一現的想法,所以感覺效果還好。先說思路,想做一個立方框裡套的一個立方體。本來呢,我是很想把CSS部分簡化,看能不能只用一套立方體的定義來實現,後來呢,嘗試了一下就放棄了,所以不辭辛苦的又造了一個小的立方體出來。CSS部分就不重複了,無非改了一下寬度、高度、位移值的定義。這裡想說的是關於旋轉角度的定義。
關於立方體旋轉角度,我們是這樣定義的:

@keyframes content{
to{transform:rotateX(360deg) rotateY(360deg);}
}複製程式碼

這裡我要做的小立方體,容器命名為content2,為了讓效果更出彩,我希望作為核心的小立方體與外面的大立方體旋轉方向相反,如果這麼定義transform:rotateX(-360deg) rotateY(-360deg),那就很無語了,因為這樣會得到下面這種神同步的兩個立方體。


正確的定義方法如下:

@keyframes content2{
0%{transform:rotateX(-180deg) rotateY(-180deg);}
100%{transform:rotateX(180deg) rotateY(180deg);}
}複製程式碼

DuangDuangDuang,看下效果如何(順手改了一把透明度):


這超時空的感覺。科技感滿滿有木有。有時候不得不感慨,CSS3真是逆天啊。不過這裡總是有一種轉著轉著核立方體超過框立方體的瞬間,待有空再優化。

3. 配合描邊動畫的3D動效

先把小立方體刪了。關於描邊動畫可以看看我以前的文章,有詳解,這裡只放CSS部分和效果。我希望得到一個在旋轉的過程中進行描邊的動畫。每個<SVG>只需要增加一個描邊動畫就可以了。DOM部分不用處理,CSS需要增加一個描邊動畫的設定:

@keyframes dash {
to {
stroke-dashoffset: 0;
}
}複製程式碼

然後每個<SVG>去呼叫這個描邊動畫,做好延遲時間的定義。因為每個矩形的周長相同,都是800,所以我進行了統一的定義。

#cubic1{transform:translateZ(100px); animation: dash 1s linear forwards;}
#cubic3{transform:rotateX(90deg) translateZ(-100px);animation: dash 1s linear 1s forwards}
#cubic2{transform:translateZ(-100px); animation: dash 1s linear 2s forwards}
#cubic4{transform:rotateY(-90deg) translateZ(100px);animation: dash 1s linear 3s forwards }
#cubic5{transform:rotateX(-90deg)translateZ(-100px);animation: dash 1s linear 4s forwards }
#cubic6{transform: rotateY(90deg) translateZ(100px); }
.content SVG {opacity:1;position: absolute;width:200px; height:200px;stroke-dasharray: 800; stroke-dashoffset: 800;}  /*每個矩形的周長是800*/複製程式碼

看一下效果如何:

這裡這個動畫效果並不是很完美,主要是因為每個矩形都有重合的邊,這也是最後一個矩形沒有給任何描邊動畫的原因,因為輪到這last one,自己的邊都被四鄰完成了。要想做的盡善盡美,需要把矩形的定義用<polyline points=""/>這種定義多邊形的方法去改寫,並嚴格定義起點終點的位置以及描邊引數。包括做不同顏色描邊,這裡我就不再費時間去修改了,總之要得出的結論是,結合每個<SVG> 的動畫進行疊加能夠得到歎為觀止的效果。

4. 配合位移動畫的3D動效

做完描邊動畫,仍然來個基礎的,和位移動畫疊加。位移動畫比描邊動畫略為複雜的原因在於描邊動畫不用考慮6個<SVG>座標系的變化,而位移動畫則受到各自座標系的影響,不過這裡用分離的思想來理解,我們把位移動畫附加給<SVG>裡面的元素,各自<SVG>包含獨立的位移動畫,然後<SVG>進行組合立方體的3D旋轉及Z軸位移,最後包含<SVG><div>再進行3D旋轉動畫。後面的兩步是使用的模板,那隻剩下第一步要完成,就是各自<SVG>包含的獨立的位移動畫。
先看下拆解的立方體的示意圖:

為了偷懶,我把位移動畫分成了兩類,立方體1和2共用垂直方向的位移動畫,3、4、5、6共用水平方向的位移動畫。組合後的立方體如下所示:


CSS部分新增兩個位移動畫

@keyframes move1 {
  to {transform:translateY(160px);} /*矩形寬40,移動160*/
}
@keyframes move2 {
to {transform:translateX(160px);}
}
.move1{animation: move1 2s ease alternate infinite }
.move2{animation: move2 2s ease alternate infinite }複製程式碼

DOM部分,只需要按我們的分類, 把定義了垂直位移動畫的矩形

<rect  class="move1" height="40" width="200" x="0" y="0"/>複製程式碼

塞到cubic1cubic2<SVG>中。

把定義了水平位移動畫的矩形

<rect   class="move2"  height="200" width="40" x="0" y="0"/>複製程式碼

塞到cubic3cubic4cubic5cubic6<SVG>中。
就可以得到下面這種疊加位移動畫效果的旋轉立方體了。(為了效果炫酷,把背景色改成了暗黑系,改改顏色、透明度什麼的)


再次宣告一遍,用<SVG>來搭建立方體,真的比<div>好很多。尤其在這種實現疊加動畫動效上。

5. 配合旋轉動畫的3D動效

基礎的動畫除了上面的描邊、位移,定然是少不了旋轉動畫咯。不過有了上面的基礎,相信旋轉動畫很輕鬆就可以完成。這裡,我們前面用的矩形<rect>要暫時退出歷史舞臺了,現在要用個更適合做旋轉動畫的二次元元素,充滿魔力的六芒星!六芒星的繪製可以直接用多邊形<polygon>完成,不過我說過因為我懶,所以我是直接AI畫完匯出的。
CSS裡定義旋轉動畫如下:

@keyframes magic{
to {transform:rotate(360deg);}
}
.magic{animation:magic 2s linear  infinite; 
transform-origin:50% 50%}複製程式碼

DOM結構中,需要修改的,僅僅是把組成六芒星的路徑塞進每個<SVG>裡。只拿其中一個為例,其他都是貼上複製的體力活。

<svg   id="cubic1" xmlns="http://www.w3.org/2000/svg" >
<rect  class="base" height="200" width="200" x="0" y="0"/>
 <g class="magic"><!--以下為組成六芒星的路徑-->
<path d="M100,20l70.645,122.36H29.355L100,20 M100,18L27.623,143.36h144.753L100,18L100,18z"/>
<path d="M170.645,57.64L100,180L29.355,57.64L170.645,57.64 M172.377,56.64l-144.753,0L100,182L172.377,56.64L172.377,56.64z"/>
</g>
</svg>複製程式碼

再看一下六個面都疊加的動畫效果

效果好壞先不說,你就說暈不暈!暈不暈!反正我做的時候,看了一眼效果,嚇得趕緊關閉視窗,轉的太噁心了。反正噁心的受不鳥了,索性再噁心點,改了不同的顏色,又疊加了個半透明的圓形,調整了一下轉速。再看看效果:


好吧,反正怎麼改都不滿意,知道有這麼個玩意就行了。

6. 六個面獨立進行動畫

前面的幾個動效,不管怎麼說,都是用了相同的動畫疊加,要麼一起轉(暈啊,吐啊),要麼一起移動,要麼一起描邊,那麼如果是每個<SVG>進行不同的動效再疊加行不行啊?當然可以啊。這是我們選擇<SVG>做立方體的初衷,就是要把它的作用發揮最大化。下面就來一個每個<SVG>都不同,動效也不同的效果。下面先修改<SVG>。(圖片來源於網路,不想做不想做,W( ̄_ ̄)W)


好吧,我承認,把<SVG>修改之後,承諾的六種不同的效果我不想做了。手累到抽筋,下次再說。88。最後一個動畫算是沒結尾,下次給動物分別做上動態表情~

相關文章