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

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

1.第一步,不管如何你須要作一下動畫底圖

由於原效果有三十種動物,我固然不會閒到每個都作一遍,因此就挑本身心中喜歡的來幾個就好。爲了避免讓各位看官失望,我會附上可複用的代碼並註明增長新的圖形的使用方法,想作三十張或者三百張的,隨意。先拿第一張來講:css

這是我在AI中幾乎徹底仿照原圖繪製的,對於設計師來講,作這種圖分分鐘鐘的事,大家比我溜,我是懶人作法,把底圖扔上,而後比着作出了一堆三角形,這個不用太精確的,而後各個碎片按原圖着色就能夠了。若是看這篇文章的恰好是諸位前端大神們,嗯,去給美膩的UI妹紙買些零食吧,只能幫到你這裏了。 一共有多少個三角形的碎片呢? 33片,請記住這個數字, 33,後面咱們再說緣由。
固然了,碎片數不須要一個個的去數,由於當存爲SVG格式後,打開時,會有一些 <polygon points="" />的標籤,每一個 <polygon>對應一個碎片,看看行數就好了(如下這句話僅針對無代碼基礎的設計師小夥伴,去下個notepad打開你的SVG文件,代碼的可讀性會增強)。 固然了,一張圖是沒法實現變形的,有些地方來不得偷懶,索性把那兩張都作了吧,我選了鯨魚和青蛙。

鯨魚的碎片只有 30片,若是你看過個人其餘關於變形動畫的文章 好比這篇 ,應該有個基礎的瞭解,首先碎片的數量是要相等的,因此鯨魚加了 3片白雲(或者確切的說是3個 <polygon>)來補齊數量。

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

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

首先,咱們須要改變SVG文件的DOM結構,目前導出來的SVG文件除了一個背景的矩形<rect>標籤,剩下的應該都是<polygon>標籤了,舉個例子,看看你的是否是和個人同樣。 這是裏面的任意一個碎片(好比是鳥bird),這個動畫總體的思路就是每一個碎片變形的組合,以上面的爲例,要變形的鯨魚whale的 <polygon>標籤以下: 前端

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

若是是內聯的樣式,那CSS3能夠直接黯然離場了,還談什麼動畫。如今要作的是,把這些內聯的屬性通通扔到CSS部分裏去,而後經過d:path屬性的變化來獲得變形動效。java

@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>標籤,獲取這個動畫屬性就能夠了。web

<polygon id ="p2" />
複製代碼

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

這裏不管用什麼辦法,總之把全部碎片對應的<polygon>points的值轉化成CSS3中的d值。好比,好比,我是用的萬能的excel的強大的Find公式(嵌套了多個也挺麻煩的)來完成的(從未想過,有朝一日會用excel來拼接代碼……),各路大神可能會有其餘方法,正則表達式什麼的,我不懂,大家各顯神通, 總之,結果要是標準的,這是咱們變形動畫的基礎。至於順序,不重要,按照默認生成的順序來就能夠了。若是不是把全部的33個碎片都列上,整個變形其CSS3和DOM結構是很是簡單的。因此,這個動效,只是繁瑣,遠稱不上覆雜。bash

@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結構以下svg

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

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

已經具有了雛形了,記得,上面我準備了三幅圖,但這裏我只作了從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>
複製代碼

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

如今,這個動畫效果已經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" 的按鈕,僅此而已。人肉親測有效,見下圖:

鑑於原網站僅支持上下順序查看,而咱們支持任意切換,因此,此處應該有掌聲。

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

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

思路很簡單,把須要動的部分從新定義一個動畫屬性,以鳥的尾巴爲例,由於肢體的擺動都是有關節的,因此用了旋轉的變形屬性 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,能夠去預覽,怎麼改爲本身想要的圖形,我想在上面已經說的很清楚了,玩起來咯。

相關文章
相關標籤/搜索