在受到SVG+CSS3動畫仿作草莓音樂節宣傳視訊的傷害後,一直想找個簡單唬人的東西做一做來平復一下悲憤的心情。翻了下收藏夾,找到了一個珍藏了很久的存貨,三十種瀕危動物的碎片動畫效果。有時候,很多創意來自於別人,別不承認,戳戳看,很驚豔 。以前寫過CSS3實現lowpoly動畫效果的文章,雖然同為lowpoly效果,其實那個的實現難度要比這個高的多,也更加繁複,還用到了CSS的選擇器,但是,還是那句至臻名言,創意遠比技藝重要,這個動物碎片的創意曾讓我驚為天人。設計師小夥伴不用害怕,最終效果,如果耐心的把文章看完,應該是可以做出來的,拿去嚇一嚇前端也是極好的,至於前端童鞋們,你們可以跳過直接看第三部分了,或者第四部分留的大坑。不廢話,直接走起。
1.第一步,無論如何你需要做一下動畫底圖
因為原效果有三十種動物,我當然不會閒到每一個都做一遍,所以就挑自己心中喜歡的來幾個就好。為了不讓各位看官失望,我會附上可複用的程式碼並註明增加新的圖形的使用方法,想做三十張或者三百張的,隨意。先拿第一張來說:
這是我在AI中幾乎完全仿照原圖繪製的,對於設計師來說,做這種圖分分鐘鐘的事,你們比我溜,我是懶人做法,把底圖扔上,然後比著做出了一堆三角形,這個不用太精確的,然後各個碎片按原圖著色就可以了。如果看這篇文章的剛好是諸位前端大神們,嗯,去給美膩的UI妹紙買些零食吧,只能幫到你這裡了。 一共有多少個三角形的碎片呢?33片,請記住這個數字,33,後面我們再說原因。當然了,碎片數不需要一個個的去數,因為當存為SVG格式後,開啟時,會有一些
<polygon points="" />
的標籤,每個<polygon>
對應一個碎片,看看行數就行了(以下這句話僅針對無程式碼基礎的設計師小夥伴,去下個notepad開啟你的SVG檔案,程式碼的可讀性會加強)。
當然了,一張圖是無法實現變形的,有些地方來不得偷懶,索性把那兩張都做了吧,我選了鯨魚和青蛙。
鯨魚的碎片只有30片,如果你看過我的其他關於變形動畫的文章比如這篇 ,應該有個基礎的瞭解,首先碎片的數量是要相等的,所以鯨魚加了3片白雲(或者確切的說是3個<polygon>
)來補齊數量。
這裡說明一點,無論用哪種做圖軟體,AI或者sketch,切記基礎圖形一定是三角形,不要引入任何其他形狀。也就是說匯出的每個
<polygon poins="">
裡面的座標數量是相等的,會有三組或者四組。(AI另存和匯出為兩種方法生成的SVG是不同的,但四組的最後一組與第一組是重複的,推薦另存為SVG格式,此坑已經踩過)
2.第二步,現在,要想辦法讓碎片變形了
首先,我們需要改變SVG檔案的DOM結構,目前匯出來的SVG檔案除了一個背景的矩形<rect>
標籤,剩下的應該都是<polygon>
標籤了,舉個例子,看看你的是不是和我的一樣。
<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個 -->
複製程式碼
先享受一下辛苦工作的效果:
已經具備了雛形了,記得,上面我準備了三幅圖,但這裡我只做了從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,可以去預覽,怎麼改成自己想要的圖形,我想在上面已經說的很清楚了,玩起來咯。