以前寫了一篇Canvas畫圖-一個比想象中更騷氣的圓(漸變圓環),其實SVG也能夠實現相似的效果,並且二者api驚人的類似。javascript
SVG是一種矢量圖形,在圖形改變尺寸的狀況下質量不會損失。css
相比canvas,svg有一個很大的優點就是內聯進html的時候能夠像操做dom同樣操做svg,這樣作起動畫來很是方便。html
本文不會介紹svg的基礎知識,不過也沒涉及什麼複雜的東西,基於xml的語法仍是比較好理解的。java
指望實現的效果和Canvas同樣是顏色非對稱的沿着圓周進行漸變。android
和以前講canvas同樣,svg也有線性漸變和徑向漸變,這裏主要講線性漸變,徑向漸變api差異不大。git
老規矩,上代碼:github
<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="595.28px" height="841.89px" viewBox="0 0 595.28 841.89" enable-background="new 0 0 595.28 841.89" xml:space="preserve">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="213.0787" y1="303.3227" x2="384.1807" y2="303.3227">
<stop offset="0.107" style="stop-color:#00A29A"/>
<stop offset="0.1301" style="stop-color:#28A891"/>
<stop offset="0.1968" style="stop-color:#76B874"/>
<stop offset="0.2649" style="stop-color:#9FC758"/>
<stop offset="0.3339" style="stop-color:#BBD338"/>
<stop offset="0.4041" style="stop-color:#CDDA06"/>
<stop offset="0.4761" style="stop-color:#D7DE00"/>
<stop offset="0.5527" style="stop-color:#DAE000"/>
<stop offset="0.9265" style="stop-color:#F39800"/>
</linearGradient>
<circle fill="none" stroke="url(#SVGID_1_)" stroke-width="16" stroke-miterlimit="10" cx="306.385" cy="355.208" r="77.551"/>
</svg>複製代碼
這個是直接從AI裏導出的,也能夠嘗試使用別的SVG編輯器,其中linearGradient
就是定義一個線性漸變,和Canvas中的ctx.createLinearGradient
一個意思,stop
標籤就相似Canvas中的grd.addColorStop
方法,一樣是設置漸變點,這裏給這個漸變設置了一個id,id="SVGID_1_"
。canvas
下面的那個circle
標籤就是定義一個圓,cx,cy,r分別是圓心座標和半徑,fill和stroke分辨對應canvas中的fillStyle和strokeStyle,stroke-width對應canvas中的lineWidth。api
和以前給canvas版的騷氣圓環用漸變同樣,svg的實現也是定義一個線性漸變,而後讓圓用這個漸變來描邊stroke="url(#SVGID_1_)"
dom
實際上出來的效果,和Canvas漸變是殊途同歸,即便svg有路徑的概念,漸變也沒有按照路徑來漸變,而是和canvas同樣從左到右,上下顏色是對稱的。
如圖:
Canvas的非對稱漸變圓環咱們藉助了ctx.createPattern
,google一下,svg裏一樣有個<pattern>
。
這裏爲了方便,我把要用到的圖片base64進去了,實際上用線上圖片也能夠。
代碼以下,省略base64的內容:
<svg height="108" width="108" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<pattern id="fill-img" patternUnits="userSpaceOnUse" width="108" height="108">
<image xlink:href="data:image/png;base64,xxxxxxxxxxx" x="0" y="0" width="108" height="108">
</image>
</pattern>
</defs>
<circle fill="none" stroke="url(#fill-img)" stroke-width="10" stroke-miterlimit="1" cx="54" cy="54" r="49" >
</circle>
</svg>複製代碼
和canvas同樣,定一個<pattern>
,而後給圓描邊的時候用這個東東。
出來的效果:
看了以前Canvas的文章的話,svg代碼仍是比較簡單的,而後咱們來加個動畫。
SVG動畫其實是讓路徑動起來,要讓路徑動起來首先要了解stroke-dasharray和stroke-dashoffset這兩個屬性。
stroke-dasharray 表示用虛線描邊。可選值爲none,
stroke-dasharray="308 1000"
中,308表示虛線中的線段的長度,而1000表示兩個線段間的長度是1000px。其實這個dasharray能夠不僅兩個值,能夠有不少個,會循環依次用到線段和空白之間。
stroke-dashoffset 表示虛線的起始偏移。可選值爲:
如今就來試一試,只須要修改circle
元素的代碼就能夠了:
<circle fill="none" stroke="url(#fill-img)" stroke-width="10" stroke-miterlimit="1" cx="54" cy="54" r="49" stroke-dasharray="308 1000" stroke-dashoffset="100">
</circle>複製代碼
以下圖:
缺的那一塊就是由於虛線的空白部分被移出來了,這裏r設置49和Canvas的原理同樣,想畫看起來半徑54的圓,須要用54減去描邊寬度的一半,54-10/2,而這裏stroke-dasharray
的第一個數,我這裏設置的是圓的周長,2Math.PI49=307.8760800517997 約等於308啦,至於第二個數,設大一點就好,大過圓的周長就能夠了。
想要作動畫就不斷的改變stroke-dashoffset
的值讓虛線的空隙動起來就能夠了,svg自己支持屬性的動畫,稍微改動一下代碼:
<circle fill="none" stroke="#e5ece7" stroke-width="10" stroke-miterlimit="1" cx="54" cy="54" r="49"/>
<circle fill="none" stroke="url(#fill-img)" stroke-width="10" stroke-miterlimit="1" cx="54" cy="54" r="49" stroke-dasharray="308 1000" stroke-dashoffset="308" stroke-linecap="round" transform="rotate(-88 54 54)">
<animate attributeName="stroke-dashoffset" begin="0s" dur="1.5s" from="308" to="0" repeatCount="indefinite" />
</circle>複製代碼
這裏我把circle的初始stroke-dashoffset
改爲308,表示從空白開始,animate
標籤中attributeName
表示動畫屬性是stroke-dashoffset,begin
表示開始的延時,dur
表示時間整個動畫的時間,frome
和to
表示初始值和最終值,repeatCount
表示重複次數,這裏是無限次。總體和CSS3動畫仍是很像的。
這裏還有一個stroke-linecap="round"
和Canvas的ctx2.lineCap="round";
做用同樣,是設置描邊的兩頭是圓形。
另外我還在上面加了一個圓,用來作底色,同時給作動畫的圓作了一個旋轉transform="rotate(-88 54 54)"
用來改變起始點。
效果以下:
大體瞭解了SVG動畫的原理以後,其實SVG還能夠用CSS3的transition和animation來作動畫。
添加css:
.animate-item {
transition: stroke-dashoffset 1.5s ease;
}複製代碼
添加js:
setTimeout(function(){
$(".animate-item").css("stroke-dashoffset",94);
}, 1000)複製代碼
前面說過svg聯進html的時候能夠像操做dom同樣操做svg,這裏修改了一下圓環,給了一個class.animate-item
修改圓環:
<circle class="animate-item" fill="none" stroke="url(#fill-img)" stroke-width="10" stroke-miterlimit="1" cx="54" cy="54" r="49" stroke-dasharray="308 1000" stroke-dashoffset="308" stroke-linecap="round" transform="rotate(-88 54 54)">
</circle>複製代碼
效果以下:
至此,騷氣圓環SVG版也就完成了,整體上來講svg的實現更簡單,作動畫的代碼也比較少,相對於canvas須要佔用js線程進行必定量的計算來講,svg的性能要好一些。
不過svg在android4.3以上纔有比較好的支持,相對來講canvas的支持就比較好了。
完整代碼: github.com/bob-chen/ca…