“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇

泱泱發表於2018-04-10

在受到SVG+CSS3動畫仿作草莓音樂節宣傳視訊的傷害後,一直想找個簡單唬人的東西做一做來平復一下悲憤的心情。翻了下收藏夾,找到了一個珍藏了很久的存貨,三十種瀕危動物的碎片動畫效果。有時候,很多創意來自於別人,別不承認,戳戳看,很驚豔 。以前寫過CSS3實現lowpoly動畫效果的文章,雖然同為lowpoly效果,其實那個的實現難度要比這個高的多,也更加繁複,還用到了CSS的選擇器,但是,還是那句至臻名言,創意遠比技藝重要,這個動物碎片的創意曾讓我驚為天人。設計師小夥伴不用害怕,最終效果,如果耐心的把文章看完,應該是可以做出來的,拿去嚇一嚇前端也是極好的,至於前端童鞋們,你們可以跳過直接看第三部分了,或者第四部分留的大坑。不廢話,直接走起。

1.第一步,無論如何你需要做一下動畫底圖

因為原效果有三十種動物,我當然不會閒到每一個都做一遍,所以就挑自己心中喜歡的來幾個就好。為了不讓各位看官失望,我會附上可複用的程式碼並註明增加新的圖形的使用方法,想做三十張或者三百張的,隨意。先拿第一張來說:

“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇
這是我在AI中幾乎完全仿照原圖繪製的,對於設計師來說,做這種圖分分鐘鐘的事,你們比我溜,我是懶人做法,把底圖扔上,然後比著做出了一堆三角形,這個不用太精確的,然後各個碎片按原圖著色就可以了。如果看這篇文章的剛好是諸位前端大神們,嗯,去給美膩的UI妹紙買些零食吧,只能幫到你這裡了。 一共有多少個三角形的碎片呢?33片,請記住這個數字,33,後面我們再說原因。
當然了,碎片數不需要一個個的去數,因為當存為SVG格式後,開啟時,會有一些<polygon points="" />的標籤,每個<polygon>對應一個碎片,看看行數就行了(以下這句話僅針對無程式碼基礎的設計師小夥伴,去下個notepad開啟你的SVG檔案,程式碼的可讀性會加強)。 當然了,一張圖是無法實現變形的,有些地方來不得偷懶,索性把那兩張都做了吧,我選了鯨魚和青蛙。

“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇

“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇
鯨魚的碎片只有30片,如果你看過我的其他關於變形動畫的文章比如這篇 ,應該有個基礎的瞭解,首先碎片的數量是要相等的,所以鯨魚加了3片白雲(或者確切的說是3個<polygon>)來補齊數量。

這裡說明一點,無論用哪種做圖軟體,AI或者sketch,切記基礎圖形一定是三角形,不要引入任何其他形狀。也就是說匯出的每個<polygon poins="">裡面的座標數量是相等的,會有三組或者四組。(AI另存和匯出為兩種方法生成的SVG是不同的,但四組的最後一組與第一組是重複的,推薦另存為SVG格式,此坑已經踩過)

2.第二步,現在,要想辦法讓碎片變形了

首先,我們需要改變SVG檔案的DOM結構,目前匯出來的SVG檔案除了一個背景的矩形<rect>標籤,剩下的應該都是<polygon>標籤了,舉個例子,看看你的是不是和我的一樣。 這是裡面的任意一個碎片(比如是鳥bird),這個動畫整體的思路就是每個碎片變形的組合,以上面的為例,要變形的鯨魚whale的<polygon>標籤如下:

<polygon points="W1,W2 W3,W4 W5,W6" style="fill: #…"/>  
複製程式碼

如果是內聯的樣式,那CSS3可以直接黯然離場了,還談什麼動畫。現在要做的是,把這些內聯的屬性統統扔到CSS部分裡去,然後通過d:path屬性的變化來得到變形動效。

@keyframes p2{
0% {d:path('MB1,B2LB3,B4LB5,B6z');fill:#…}  /*繪製bird其中之一碎片*/
100%{d:path('MW1,W2LW3,W4LW5,W6z');fill:#…} /*繪製whale其中之一碎片*/
}
#p2{animation:p2 2s ease both;}	
複製程式碼

而在DOM結構中,只要保留一個簡單的<polygon>標籤,獲取這個動畫屬性就可以了。

<polygon id ="p2" />
複製程式碼

在用CSS屬性來繪製碎片時,格式記得一定要正確,填充色比較好理解,但所有的頂點座標在寫入d:path時都要轉成Mxy Lx1y1 Lx2y2 Lx2y2 z這種樣式,具體不再解釋了,屬於基礎知識。

這裡無論用什麼辦法,總之把所有碎片對應的<polygon>points的值轉化成CSS3中的d值。比如,比如,我是用的萬能的excel的強大的Find公式(巢狀了多個也挺麻煩的)來完成的(從未想過,有朝一日會用excel來拼接程式碼……),各路大神可能會有其他方法,正規表示式什麼的,我不懂,你們各顯神通, 總之,結果要是標準的,這是我們變形動畫的基礎。至於順序,不重要,按照預設生成的順序來就可以了。如果不是把所有的33個碎片都列上,整個變形其CSS3和DOM結構是非常簡單的。所以,這個動效,只是繁瑣,遠稱不上覆雜。

@keyframes bg{
0%{fill:#A4C5EA}
100%{fill:#73DBE0}
}
#bg{animation:bg 2s ease both;}
/*定義背景色的變化*/

@keyframes p(n){
0% {d:path('');fill:#…}
100%{d:path('');fill:#…;}
}
#p(n){animation:p(n) 2s ease both;}
/*n=1,2,3,4……33  一共需要定義33個*/
複製程式碼

DOM結構如下

<rect width="" height="" id="bg" />
<!--背景變色動效-->
<path id="p(n)" />
<!-- n=1,2,3,4……33  一共需要33個 -->
複製程式碼

先享受一下辛苦工作的效果:

“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇

已經具備了雛形了,記得,上面我準備了三幅圖,但這裡我只做了從bird到whale的變形動畫,並沒有啟用第三張圖片frog,因為這一部分只是原理,下面才是重點。

3.第三步,比原效果更優化,我們支援互動

這裡感謝Java大牛Hevo的幫助,是的,JavaScript只是隨隨便便懂一點,在提供了變形動畫思路之後,輕鬆丟過來幾行我看不懂的javascript指令碼來實現互動,順便可以後期擴充套件。原網站的動效是前後點選切換,既然求助了Hevo同學,自然要做的優美動人一些。最後效果是支援任意圖形之間的變形。現在,我把各部分重新放上來。javascript部分如下

$(function(){
	$("button").bind("click", function(){
		var turnTo = $(this).attr("turnTo");
		// for backgroud changing
		var bg = $("#p_bg");
		var bg_fill = bg.css("fill")
		bg.css("fill", bg_fill).css("animation", turnTo + "_bg 2s ease both")
		
		// for lowpoly changing
		$.each($("path"), function(i, n){
			var d = $(n).css("d");

			var fill = $(n).css("fill");
			
			$(n).css("d", d).css("fill", fill);
			$(n).css("animation", turnTo + "" + (i+1) + " 2s ease both");
		});
		
	})
})
複製程式碼

這個,這個,讓我怎麼解釋呢?就是寫了個迴圈然後根據點選按鈕不同給CSS對應賦值並呼叫該變形動畫屬性。

CSS部分如下

@keyframes bird_bg{
to{fill:#A4C5EA;}
}
/* 定義bird的背景色 */

@keyframes bird(n){
to{d:path('');fill:#…;}
}
/*定義bird碎片最終變形的效果 n=1,2,3……33*/、

@keyframes whale_bg{
to{fill:#73DBE0;}
}
/* 定義whale的背景色 */

@keyframes whale(n){
to{d:path('');fill:#…;}
}
/*定義whale碎片最終變形的效果 n=1,2,3……33*/

@keyframes frog_bg{
to{fill:#ffcffc;}
}
/* 定義frog的背景色 */

@keyframes frog(n){
to{d:path('');fill:#…;}
}
/*定義frog碎片最終變形的效果 n=1,2,3……33*/

#p_bg{
fill:#ffd480;
animation:bird_bg 2s ease both;
}
/*定義初始畫面的背景*/
#p(n){
d:path('');fill:#…;
animation:bird(n) 2s ease both;
}
/*定義初始畫面的路徑 n=1,2,3……33*/

/* 定義按鈕樣式 */  
此處省略若干…… 喜歡什麼樣式去copy些下來吧
複製程式碼

DOM部分

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
	width="960"  height="720" viewbox="0 0 960 720">
<rect width="960" height="720" id="p_bg"/><!--此為背景-->
<path  id="p(n)" />  <!--n=1,2,3……33-->
</svg>
<p>
<button type="button" turnTo="bird" class="">BIRD</button> 
<button type="button" turnTo="frog" class="">FROG</button> 
<button type="button" turnTo="whale" class="">WHALE</button> 
</p>
複製程式碼

如果省略那一堆碎片的路徑和填充色,整個程式碼讀起來還是清爽乾淨以及輕鬆愉快的。

“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇
現在,這個動畫效果已經up了一個檔次了。關於初始畫面,那個LOW,絕壁不是效果太low的意思啊,本心是想做個LOWPOLY的lowpoly效果,無奈生成的碎片超過了33片了,又懶得改其他部分(比如我可以給所有的都補充上空白路徑d:path('M0,0L0,0L0,0L0,0z')(如果你瞭解路徑的繪製規則,應該能輕易看出來這是一個虛擬路徑),來補齊所有的數量,但是,懶且麻煩就算了,low就low吧。

因為gif格式比較大,受限,所以快速點選的幾下,想玩的愉快的到Demo演示地址裡去吧。在文末,我會貼上我的codepen演示地址。

那麼設計師小夥伴們怎麼拿去用呢?看一下我的demo的命名的規則,所有的元素,我會盡量保持統一的命名,比如,你要增加一張圖片是sheep(我知道這是羚羊antelope,但這個單詞超出認知範疇了,看不懂)。那麼,要定義的有 圖片背景色sheep_bg,sheep(n)的各個碎片的d:path屬性,以及增加一個 turnTo="sheep" 的按鈕,僅此而已。人肉親測有效,見下圖:

“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇
鑑於原網站僅支援上下順序檢視,而我們支援任意切換,所以,此處應該有掌聲。

4. 這個效果可以更好,只是不知道怎麼用JavaScript控制

對於這一套動畫的主體部分是動物之間的變形,但仍有小細節,比如身體某個部位依然可以動。以最初的那個bird turn to whale,在變形動畫之前,bird尾巴部分可動,變形結束後,whale的鰭可動,我自己做了一下效果,大概是下面這樣的。

“破碎-重組-破碎” CSS3實現Lowpoly風格變形動畫終極篇
思路很簡單,把需要動的部分重新定義一個動畫屬性,以鳥的尾巴為例,因為肢體的擺動都是有關節的,所以用了旋轉的變形屬性transform:rotate()

@keyframes bird_tail{
to {transform:rotate(6deg);}
}
#bird_tail{animation:bird_tail 0.5s ease-in-out 4 alternate;transform-origin:} 
/*準確定義旋轉的基點transform-origin很重要,就是關節位置*/
複製程式碼

而鯨魚則巢狀了兩個部分,整體的一個位移,**transform:translateX()**以及區域性的幾片組合的旋轉,再設定好時間延遲,並不是很困難。

鑑於此坑太深,不打算碰。實現這種效果後,剩下的丟給了Hevo同學,看能不能用JavaScript實現兩次按鈕切換之間的區域性變形的迴圈動畫。

最後的最後,小結一下,對於這個動效而言,看上去逼格滿滿,但其實只是一個簡單的d:path()屬性值改變的變形效果。但因為單變多,所以產生了這種驚歎的效果。codepen地址Lowpoly transform animation,可以去預覽,怎麼改成自己想要的圖形,我想在上面已經說的很清楚了,玩起來咯。

相關文章