用SVG動畫重現布爾運算的設計過程

這是在作圖時突然迸發的靈感(是的,偶爾也會有那么一瞬間頭腦開竅),作為設計師小伙伴們,平時用的最多的應該是布爾運算吧,基礎圖形的加加減減,得到任意的形狀。就不說經典的Apple了,比如網易云音樂圖標,你如果直接放上這個,似乎沒什么。


但放上布爾運算過程的設計稿(所有基礎圖形的輪廓),瞬間高大上起來,滿滿的設計感。


所以在做矢量圖的過程就突然想到如果能用SVG結合CSS3的動效來還原這個設計過程,也不失為一個好玩的效果,當然了,不會那么巧剛好用到所有的四種運算,只是用動畫過程演示一遍,此為目的。因為自己的底子就很弱,所以選了一個臨摹的圖形,眾位客官湊合看吧。

1.準備工作——圖形分層

每次在做SVG動效之前,都會給自己一點時間思考一下動畫完成的思路,以及用什么屬性來實現,正所謂多點思考,少點勞作,或者換句話說,“不能用戰術的勤奮來代替戰略的懶惰”。
先放一張成品的效果圖,如下,就是這只萌萌的小象


AI中做布爾運算雖然用路徑查找器極其方便,且能切割,任意玩,但是修改起來卻沒有PS那么方便,給做完運算后的調整不是很方便的說。比如十幾甚至更多個形狀的布爾運算在PS里玩起來還算輕松,左挪右挪上層下層的調節么有壓力,在AI里那要被玩壞了。所以第一步,要在AI里做好分層。注明一點,這些是要在作圖之前就確定的。
我把小象分成三個部分,身體、頭部和尾巴,目的就是為了減少每個部分的基本形狀的數量。
AI中進行過布爾運算后的形狀導出后是得到的結果的路徑,這就不歡樂了,舉個簡單的例子:


上面兩個圓形,相交之后得到的形狀,導出后是<path d="">,完全不見兩個圓形<circle>的蹤跡,既然我們是還原過程,過程,就需要把原運算前的路徑保留,怎么破?在進行運算之前原位復制到新的圖層中唄。以小象的身體為例,我保留了兩個圖層,運算后和運算前的,這些路徑都是我需要用到的。

2.創建圖形過程的動畫

鑒于自己這渣渣一般的水平,圖形加減那一套過程就不拿出來嘚瑟了,還是留著自家珍藏吧,這里只說如何用動畫表現出來。各位設計師回想一下自己的創建基本形狀的過程,是不是選擇形狀后在畫布進行鼠標拖動就可以了,嗯,這里我們主要實現的就是鼠標拖動的動畫過程。來看下面這張圖(不要給我講你是按著alt鍵巴拉巴拉的,不管,要不這動畫沒法做了 ~~~(>_<)~~~):


從左上角到右下角的拖動過程就是圖形的創建過程,而且在創建的過程中,圖形是逐漸從無到有,從小到大的。好了,廢話了半天,不不,是拋磚引玉,這就是我們實現創建圖形過程的動畫思路。

@keyframes draw{
0%{transform:scale(0,0);transform-origin:left top}
100%{transform:scale(1,1);transform-origin:left top}
}  
/*通用繪制過程的動畫定義*/

經過分析我們得出,縮放變形transform:scale()是實現這種效果的最佳方案,這里唯一要注意的是關于變形的基點,前面在涉及旋轉動畫中,更多的定義是transform-origin:center center,也就是以圓心為基點,而這里定義的是左上角,也就是left top,其實CSS的一些語法真的算是很簡單了,英語入門級。另外這里對應的left和top的值是相對位置,這也是為什么能把draw定義成通用的原因。
下面這張圖形虛線部分是為了得到身體部分創建的所有基礎圖形,實色填充的部分即為最后需要的身體部分。

基礎圖形是由5個圓形和1個矩形共同組成的。我進行了標號。


對于身體部分,是4個圓形和1個矩形與1個基礎圓形進行相減得到的。為了讓動畫過程更形象,讓基礎圓形進行了實色填充,其他形狀用虛線來表示。根據上面動畫的定義,先來實現基礎圖形的創建過程,CSS部分如下:

<style>
@keyframes draw{
0%{transform:scale(0,0);transform-origin:left top}
100%{transform:scale(1,1);transform-origin:left top}
} 
#circle0{animation:draw 1s ease;fill:#414c68;}/*基礎形狀用實色填充*/
#circle1{animation:draw 1s ease 1s backwards;}
#circle2{animation:draw 1s ease 2s backwards;}
#circle3{animation:draw 1s ease 3s backwards;}
#circle4{animation:draw 1s ease 4s backwards;}
#rect1{animation:draw 1s ease 5s backwards;}
.sketch{stroke:#c0f1ff;stroke-width:2;fill:none}/*其他形狀用描邊*/
</style>

SVG部分簡化如下(去掉了和形狀尺寸位置相關的屬性定義):

<circle id="circle0"/> <!--基礎形狀-->
<g class="sketch">  <!--其他形狀-->
<circle id="circle1" />
<circle id="circle2" />
<circle id="circle3"/>
<circle id="circle4"/>
<rect id="rect1"/>
</g>

簡單解釋一下,動畫屬性定義那里拿這個#circle1{animation:draw 1s ease 1s backwards;}為例,第一個1s是繪制時間,第二個1s是延遲時間,為了讓圖形呈現出依次創建的過程,所以延遲時間是遞增的。backwards這個屬性一定要定義,當我們給動畫定義了延遲時,我們需要定義動畫時間之外對象的狀態(animation-fill-mode),backwards表示動畫開始前應用開始屬性值,也就是我們定義的scale(0,0),換句話說,是不顯示的,這里也可以定義成both,對這個動畫效果而言,沒有區別。
現在看一下動畫效果:


嗯,基本重現了創建了基礎圖形的過程。那么下一部分來了,怎么才能過渡到運算之后的形狀呢?

3.運算過程的動畫

在做這個動畫伊始,我想到的是把相減的圖形轉化成蒙版,能行不?絕對能行,但實在是太麻煩了。記得我們還保留了運算后的圖形放到了單獨的圖層中吧?這時,需要它粉墨登場了,然后其他的圖形怎么辦?集體消失!
關于消失的方法也有很多種,隨便來個順手的就行了,我準備用蒙版。為了實現組合圖形消失以及運算后的圖形出現的過程,不得已,又定義了兩個動畫,其實做到這里的時候,已經很后悔了,遠不如好好學學AE,在AE里實現,但自己挖的坑,含著淚也要跳進去再努力爬出來啊,善始善終,硬著頭皮繼續做吧。流著淚補充了下面的動畫定義:

@keyframes skip{
0%{opacity:0}
100%{opacity:1}
} /*這是為要登場的圖形準備的*/
@keyframes combine{
0%{fill:#FFFFFF}
100%{fill:#000000}
}/*這是為要退出舞臺的圖形準備的*/

.skip{animation:skip 1s  6s both; fill:#414c68}
.combine{animation:combine 1s 6s both;}

以及:

<mask id="shade"><rect x="0" y="0" width="800" height="600" id="combine"/></mask> <!--蒙版定義-->
<g mask="url(#shade)">……</g>
<path class="skip" d=""/><!--組合后的形狀-->

<g mask="url(#shade)">是把所有的圖形又組合后,使用這個蒙版。唯一值得欣慰的是skip和combine這兩個動畫可以被復用。
插播一個小知識點,關于利用蒙版的漸隱動畫,是不能用0%{opacity:0} 100%{opacity:1} 然后填充黑色fill:#000000這種表面上看上去是蒙版漸現的方式來實現,是因為當不給蒙版定義顏色時,蒙版會被默認為黑色,因此即使開始定義了透明度為0,也會被當做黑色處理。如果實在要用的話,就套兩層蒙版,一層黑色的透明度改變,下面一層白色實色底。我只截變化的那一部分動畫來看一下:


似乎銜接的還不錯喲。

剩下的工作就是體力活了呃,需要把頭部的動畫和尾巴的動畫補充上,沒有什么特殊的,延遲的時間別弄錯了就行,這里就不說了吧。最后得到的統一的動畫是這個樣子的:


與理想中那種滿滿的設計感有差異,不過還好。下面試著來優化一下,上個色吧。

4.顏色填充過程

顏色填充的過程,與這個展示繪制動畫過程沒有什么毛線關系,就是為了好看!好看!我還能說什么呢?說什么顯示填色的過程,鬼,對于怎么展示漸變填充完美沒有思路,我就利用了一下蒙版,把已經填充好的圖形先用蒙版蓋起來,讓你們看不見看不見,然后在適當的時間,蒙版逐漸移動,露出填充好顏色圖形。為了讓蒙版顯示的效果更加自然,這里我用漸變色對蒙版進行了填充。圖示如下:

<defs>
<linearGradient id="gradient3"  x1="0" y1="0" x2="0" y2="600">
  <stop offset="0" stop-color="#ffffff"/>
  <stop offset="0.1" stop-color="#000000"/>
</linearGradient>
</defs> <!--定義的漸變類型-->

最后得到的效果如下:

另外,狠狠的告誡自己,下次再也不做這種費勁巴拉但不酷炫的效果了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,141評論 5 13
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,566評論 6 30
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,284評論 25 708
  • 在前面兩篇文章中,雖然完整描述了任意圖形的變形動畫實現方法,但最大的局限性顯而易見,那就是都是一個圖形變形成另一個...
    泱泱悲秋閱讀 1,471評論 0 0
  • 開學的第一天,因為不適應在家以外的地方,花顏很早就醒了,但她看了看白亦可和劉零零,發現她們睡得很香,沒有絲毫要睡醒...
    歡言歡語閱讀 903評論 0 0