標籤:

怎樣做一個圓環放大的動畫

最近遇到一個問題,就是怎麼做一個圓環放大的動畫,如果是用transform: scale放大的話,會導致圓環變粗,這樣看起來就不好看了,如下圖所示:

如果改成用width/height做動畫的話,動畫看起來會有點變形,如下圖所示:

這個圓圈是用border-radius: 50%畫出來的,所以width/height變大的時候,圓圈的半徑就會變大,但是在變化的過程中變形了。如果改成用padding做動畫,效果也一樣,那怎麼辦呢?一個方法是把動畫時間調小一點,這樣看起來會減輕,但終究不是根本解決辦法。

我在網上搜羅一番,也沒有找到好的辦法,有的是用JS動態計算width/height,但其實是一樣的。

最後我想到是不是可以用SVG來做動畫呢?試了一下,果然可以。

首先要用SVG來畫,之前是用html + css的方式,現在要改一下。如下代碼所示:

<svg width_="22px" height="22px"> <circle r="8" cx="11" cy="11" fill="#fff" stroke="#2492fc"/></svg>

circle表示畫一個圓,圓心在(11, 11),半徑為8px,填充白色,描邊為#2492fc,如果你設置fill="none",那麼填充色就為透明色。相信很多人對SVG比較陌生,這裡我簡單介紹一下。除了circle,其它常用的畫圖標籤元素如下圖所示:

還有一個畫路徑的path,如下圖所示:

這個是用一個在線SVG畫圖工具來出來的,畫完後會顯示SVG代碼。path裡面可以使用貝塞爾曲線,它是一種很見的曲線,在CSS的animation也會用到,用來控制動畫的速度:

貝塞爾曲線(三階)是根據四個點畫出一條光滑的曲線,這種矢量繪製曲線的方法在圖形學具有重大的意義。

SVG的基本元素就介紹到這裡,現在討論下怎麼做動畫呢?我們應該要做半徑的動畫,如下圖所示,使用animate標籤:

其中begin指定動畫的開始時機,可以是indefinite表示無限循環,或者指定具體的秒數,又或者是在某個動畫之後,還可以是事件如mouseover/click/mouseout等,上面使用mouseover,即hover的時候,半徑會從小變成到大,如果希望滑鼠移開後能縮回去,那麼可以再加一個amimate,如下代碼所示:

<svg width_="22px" height="22px"> <circle r="8" cx="11" cy="11" fill="#fff" stroke="#2492fc"> <animate attributeName="r" from="8" to="10" dur="0.3s" begin="mouseover" fill="freeze" class="magnify"/> <animate attributeName="r" from="10" to="8" dur="0.3s" begin="mouseout" fill="freeze" class="shrink"/> </circle></svg>

如果是希望用JS控制的話,可以獲取到這個animate元素,然後用它的beginElement方法開始動畫,如下代碼所示:

// 如果選中的話,就做放大的動畫if (checked) { $("animate.magnify").beginElement();}// 如果失去選中態的話就做縮小動畫else { $("animate.shrink").beginElement();}

這樣看起來動畫就會優雅很多,如下圖所示:

另外還可以用CSS的animation等控制SVG做動畫。

上面只是介紹了最最簡單的SVG動畫,更多複雜的效果可以見CSS Tricks的教程。例如可以做形狀的動畫:

又如做一個沿著路徑運動的動畫:

本篇最主要還是想說一件事:當你發現用html不太好做動畫時,可以嘗試用svg做一下,幾行svg就能做出一個很順滑的動畫。例如這篇文章《Animating Border》介紹了幾種做border變粗的動畫的方法,筆者先後使用了border-width/outline/clip-path/linear-gradient/box-shadow等,最後效果其實都不太好,還不如直接用svg做一下。


推薦閱讀:

如何製作 svg 格式的 圖標字體?
外刊君談中國第三屆CSS大會
SVG及SVG路徑動畫
用 SVG 畫小水滴

TAG:前端开发 | SVG |