有個項目需要在某個坐標顯示一個聲波擴散(不知道這個表達對不對)的動畫。

這種需求一般做法有幾種,一種做成gif圖片,然后貼上去,一種是用html+css3完成,要么就是畫上去,這畫又分兩種,一種是Canvas畫布來畫,另一種用svg來畫。
制作成gif圖片往上貼,如果有ui負責做圖,這對於前端來說是最省事的方法,只要貼上去就完了,不過這種方法有一個缺點,你能控制的有限,如果要用另一種顏色,或者改變圈數,只能重新制作一張圖片,重復替換,而且動畫的重復次數也不好控制。pass
html+css3完成,這個簡單,不過效果有限,看這里。pass
畫上去分兩種,一種canvas畫布,一種svg畫布,關於兩者的優劣比較不是這里的主體,在這里不討論。而且對於小需求來說,兩者的資源消耗差異其實也可以忽略不計。關於canvas的聲波擴散實現,看這里。
好吧,言歸正傳,既然選擇了方向,那便開始。
首先,寫一個svg畫布,寬高200px
<svg id="svgView" width="200" height="200"></svg>
然后在里面畫一個圓。
<svg id="svgView" width="200" height="200"> <circle cx="80" cy="80" r="50" stroke="#555" fill-opacity="0"></circle> </svg>
這里circle表示一個圓,圓心坐標以svgView畫布左上角為原點,向右偏移cx個單位,向下偏移cy個單位,r為圓半徑,stroke表示圓邊框填充顏色,fill表示圓內填充顏色,fill-opacity表示圓內填充透明度。完整API。
效果:

接下來添加動畫效果。這里用到了svg的SMIL animation。
<svg id="svgDom" width="200" height="200"> <circle cx="80" cy="80" r="50" stroke="#555" fill-opacity="0"> <animate attributeName="r" begin="0" from="0" to="50" dur="2s"></animate> </circle> </svg>
attributeName表示動畫進行改變的是圖像的什么屬性;begin為開始時間,單位為秒;from為開始值,to為目標值,其中from可選,dur表示動畫持續時間。如果不添加repeatCount屬性,表示動畫執行一次便結束。
效果:

我們的圖片是需要不停的擴散的,於是添加repeatCount屬性,讓其無限循環。
<svg id="svgDom" width="200" height="200"> <circle cx="80" cy="80" r="50" stroke="#555" fill-opacity="0"> <animate attributeName="r" begin="0" from="0" to="50" dur="2s" repeatCount="indefinite"></animate> </circle> </svg>
indefiniter表示無限循環至電腦死機。
效果:

設計里,我們的擴散環有三環,然后每環延遲0.5s釋放,當釋放至最大消失,由此循環。
<svg id="svgDom" width="200" height="200"> <circle cx="80" cy="80" r="50" stroke="#555" fill-opacity="0"> <animate attributeName="r" id="ani1" begin="0" from="0" to="50" dur="1.5s" repeatCount="indefinite"></animate> </circle> <circle cx="80" cy="80" r="50" stroke="#555" fill-opacity="0"> <animate attributeName="r" begin="ani1.begin + 0.5s" from="0" to="50" dur="1.5s" repeatCount="indefinite"></animate> </circle> <circle cx="80" cy="80" r="50" stroke="#555" fill-opacity="0"> <animate attributeName="r" begin="ani1.begin + 1s" from="0" to="50" dur="1.5s" repeatCount="indefinite"></animate> </circle> </svg>
其中,begin為動畫開始時間,可以設置具體的時間秒數,也可以根據animate 的id值,來獲取該id的animate動畫開始結束時間,然后添加偏移數據,來控制多個動畫的依序進行。
效果:

到這里,其實已經達到效果了,不過我們可以進一步添加一個效果,讓圓環在擴散過程中慢慢消失。並且將圓環寬度設置為5px。
<svg id="svgDom" width="200" height="200"> <circle cx="80" cy="80" r="0" stroke="#555" stroke-width="5" fill-opacity="0"> <animate attributeName="r" id="ani1" begin="0" from="0" to="50" dur="1.5s" repeatCount="indefinite"></animate> <animate attributeName="opacity" begin="0" from="1" to="0" dur="1.5s" repeatCount="indefinite"></animate> </circle> <circle cx="80" cy="80" r="0" stroke="#555" stroke-width="5" fill-opacity="0"> <animate attributeName="r" begin="ani1.begin + 0.5s" from="0" to="50" dur="1.5s" repeatCount="indefinite"></animate> <animate attributeName="opacity" begin="ani1.begin + 0.5s" from="1" to="0" dur="1.5s" repeatCount="indefinite"></animate> </circle> <circle cx="80" cy="80" r="0" stroke="#555" stroke-width="5" fill-opacity="0"> <animate attributeName="r" begin="ani1.begin + 1s" from="0" to="50" dur="1.5s" repeatCount="indefinite"></animate> <animate attributeName="opacity" begin="ani1.begin + 1s" from="1" to="0" dur="1.5s" repeatCount="indefinite"></animate> </circle> </svg>
最終效果:

到這里,這個svg版聲紋擴散動畫已經做完了。
