卡牌特效: svg不规则倒计时动效
導(dǎo)語:直播過程中,往往會有各種動畫特效增強直播效果,近期需求中,設(shè)計要求在企鵝電競PC官網(wǎng)上實現(xiàn)一種卡牌效果,在不規(guī)則圖片上疊加倒計時效果。前端項目中,往往使用css來完成動畫,像倒計時效果也可以使用css完成,但是相對來說css實現(xiàn)方案比較復(fù)雜,層次嵌套較多。倒計時動效要求覆蓋圖片的倒計時陰影為非規(guī)則且半透明的。在日常的圓環(huán)動畫中,也會有類似的倒計時效果,只不過圓環(huán)是規(guī)則的,實現(xiàn)起來比較簡單。但是基于圓環(huán)效果,再加上svg的mask特性,就可以實現(xiàn)此類特殊效果。
[ 實現(xiàn)動態(tài)圖]?
css的mask屬性可以切割圖形,實現(xiàn)不規(guī)則圖形,但是css mask屬性兼容性比較差。canvas基于像素繪制,上下文占用內(nèi)存大,多次切換上下文會造成內(nèi)存釋放慢,影響到頁面的流暢度。而svg的兼容性好,基于XML,比較輕量,而且當前特效的XML結(jié)構(gòu)比較簡單,不會影響頁面性能,鑒于當前頁面已經(jīng)有多處特效使用canvas繪制,基于性能考慮,本次方案不采用canvas實現(xiàn)。綜合對比后決定用svg來實現(xiàn)這個效果。
css(mask) | 差 | 一般 |
canvas | 好 | 一般 |
svg | 好 | 好 |
效果分為兩部分,下層部分是一張靜態(tài)圖,上層部分是倒計時效果。實現(xiàn)難點在倒計時效果上,而倒計時效果又可以分為幾部分:
1、實現(xiàn)半透明倒計時圖層,且時間可隨意設(shè)置;
2、實現(xiàn)切割半透明倒計時蒙版;
3、把蒙版作用在倒計時圖層,并覆蓋在靜態(tài)圖上;
4、組件化,可實現(xiàn)各種不規(guī)則圖形的效果;
1. 圓環(huán)效果
在一些頁面中,經(jīng)常可以看到一些圓環(huán)進度條,因為svg實現(xiàn)簡單,所以這些基本上都是用svg的實現(xiàn),svg circle是svg繪制圓形矢量圖的屬性,它支持設(shè)置以下屬性:
cx,cy:坐標位置
r:半徑
stroke-width:填充寬度
fill:填充內(nèi)容
stroke-dasharray:虛線寬度
transform:變換
下面用幾行代碼演示svg圓環(huán)圖:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <circle cx="50%" cy="50%" r="40%" stroke-width="20%" stroke="#D1D3D7" fill="none"></circle> <circle class="transformNe90" cx="50%" cy="50%" r="40%" stroke-width="20%" stroke="#00A5E0" fill="none" stroke-dasharray="100 502.7"></circle> </svg>[ svg圓環(huán)圖 ]
2. 虛線效果
實現(xiàn)這個效果的重點在circle的stroke-dasharray屬性,stroke-dasharray在SVG中表示的是描邊虛線。需要傳入兩個值,第一個是虛線的寬度,第二個是虛線之間的間距stroke-dashoffset,下面看一下用stroke-dasharray實現(xiàn)的虛線效果:
<svg width="200" height="200" viewPort="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg"> <line stroke-width="2" stroke-dasharray="5, 5" stroke="black" x1="10" y1="10" x2="190" y2="10"></line> <line stroke-width="2" stroke-dasharray="5, 10" stroke="black" x1="10" y1="30" x2="190" y2="30"></line> <line stroke-width="2" stroke-dasharray="10, 5" stroke="black" x1="10" y1="50" x2="190" y2="50"></line> <line stroke-width="2" stroke-dasharray="5, 1" stroke="black" x1="10" y1="70" x2="190" y2="70"></line> <line stroke-width="2" stroke-dasharray="1, 5" stroke="black" x1="10" y1="90" x2="190" y2="90"></line> <line stroke-width="2" stroke-dasharray="0.9" x1="10" y1="110" x2="190" y2="110"></line> <line stroke-width="2" stroke-dasharray="15, 10, 5" stroke="black" x1="10" y1="130" x2="190" y2="130"></line> <line stroke-width="2" stroke-dasharray="15, 10, 5, 10" stroke="black" x1="10" y1="150" x2="190" y2="150"></line> <line stroke-width="2" stroke-dasharray="15, 10, 5, 10, 15" stroke="black" x1="10" y1="170" x2="190" y2="170"></line> <line stroke-width="2" stroke-dasharray="5, 5, 1, 5" stroke="black" x1="10" y1="190" x2="190" y2="190"></line> </svg>[ svg虛線圖 ]
3. 實現(xiàn)圓環(huán)
從上面的虛線圖可以看出,stroke-width表示虛線的“高度”,虛線的寬度是stroke-dasharray的第一個參數(shù)值,虛線間隔是stroke-dasharray的第二個參數(shù)值。
在實現(xiàn)圓環(huán)效果時,也是這個原理,stroke-width表示圓環(huán)的邊框?qū)挾?#xff0c;stroke-dasharray的第一個參數(shù)為圓環(huán)邊框的可見長度,stroke-dasharray的第二個參數(shù)為圓環(huán)邊框的非可見長度。
如果把stroke-dasharray設(shè)置為"0 a",其中a大于等于圓環(huán)的周長時。此時整個圓環(huán)的可見長度為0,非可見長度為a,整個圓環(huán)不可見,表現(xiàn)為圓環(huán)進度條為0,若增大可見長度,便可以看到圓環(huán)進度條增長了。
[ 可見長度為0 ]
[ 可見長度為10% ]
[ 可見長度為100% ]
4. 圓環(huán)動畫
svg的animate屬性可以實現(xiàn)svg動畫,它支持設(shè)置以下屬性:
attributeName:要變化的元素屬性名稱
attributeType:CSS | XML | auto
begin,end:開始結(jié)束時間,可以是單時間或分號隔開的時間列表,常見單位有 “h”|”min”|”s”|”ms”
from, to, by, values 開始結(jié)束點
fill:表示動畫間隙的填充方式。支持參數(shù)有:freeze | remove. 其中remove是默認值,表示動畫結(jié)束直接回到開始的地方。freeze“凍結(jié)”表示動畫結(jié)束后像是被凍住了,元素保持了動畫結(jié)束之后的狀態(tài)。
repeatCount:動畫執(zhí)行次數(shù)
repeatDur:定義重復(fù)動畫的總時間
當stroke-dasharray的可見長度等于圓環(huán)的周長,此時可見長度剛好覆蓋了整個圓環(huán),基于以上的實現(xiàn),再加上動畫,就可以實現(xiàn)圓環(huán)動畫了
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <circle cx="50%" cy="50%" r="40%" stroke-width="30" stroke="#D1D3D7" fill="none"></circle> <circle cx="50%" cy="50%" r="40%" stroke-width="30" stroke="#00A5E0" fill="none" transform="matrix(0,-1,1,0,0,200)" stroke-dasharray="0 502.7"> <animate attributeType="XML" attributeName="stroke-dasharray" from="0" to="502.7" dur="10s" fill="freeze" repeatCount="10"></animate> </circle> </svg>[ 動態(tài)圓環(huán) ]
5. 實心環(huán)形動畫
接下來就是要把圓環(huán)動畫擴寬到實心環(huán)形動畫。那么若增大storke-width,會發(fā)現(xiàn)圓寬度會向內(nèi)外擴展
[ stroke-width等于半徑 ]
繼續(xù)增大stroke-width,使得stoken-width等于圓的直徑,因為設(shè)置r=”40%”,所以stroke-width=”80%”。此時填充的位置剛好覆蓋到圓的中心
這里需要注意的是stroke-dasharray的起始位置在右側(cè),而不是上方,因此,需要使用transform逆時針旋轉(zhuǎn)90°,所以通過添加class="transformNe90"旋轉(zhuǎn)整個circle動畫
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <circle cx="50%" cy="50%" r="40%" stroke-width="80%" stroke="#D1D3D7" fill="none"></circle> <circle class="transformNe90" cx="50%" cy="50%" r="40%" stroke-width="80%" stroke="#00A5E0" fill="none" stroke-dasharray="0 502.7"> <animate attributeType="XML" attributeName="stroke-dasharray" from="0" to="502.7" dur="10s" fill="freeze" repeatCount="10"></animate> </circle> </svg> <style> .transformNe90 { transform: rotate(-90deg); transform-origin: center center; } </style>[ stroke-width等于直徑 ]
此時倒計時效果剛好覆蓋了整個圓,填充的倒計時效果完成。
1. css遮罩層
了解svg蒙版,先了解一下css的遮罩mask屬性,css mask遮罩屬性是一個很古老的屬性,它的原理是黑透白不透,它是基于圖像的alpha計算遮罩程度的,顏色越深透過遮罩層的可見視圖就越多,如果是全黑就會全透,同理全白就會透不過,看起來就像把白色區(qū)域的圖形給切掉了。它支持在樣式中設(shè)置以下幾種屬性:
mask-image
mask-mode
mask-repeat
mask-position
mask-clip
mask-origin
mask-size
mask-type
mask-composite
mask-image指遮罩使用的圖片資源,所支持的圖片類型非常的廣泛,可以是url()靜態(tài)圖片資源,格式包括JPG,PNG以及SVG,使用mask-image我們可以遮罩出任意我們想要的圖形,非常強大。下面看一個用css mask實現(xiàn)的遮罩效果:
<style> .mask-image { width: 200px; height: 200px; -webkit-mask-image: url(http://imgcache.gtimg.cn/club/pgg/ams/img/pkcard_placeholder.png); mask-image: url(http://imgcache.gtimg.cn/club/pgg/ams/img/pkcard_placeholder.png); } </style> <div style="width: 200px;height: 200px; background: #00A5E0" class="mask-image"></div>[ css mask]?
2. svg蒙版
從上面這個的例子,我們可以看出,所謂遮罩,就是原始圖片只顯示遮罩圖片非透明的部分。同比,我們在svg中也使用svg的蒙版屬性mask來實現(xiàn)遮罩。
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <mask id="maskId" patternUnits="userSpaceOnUse" > <image x="0" y="0" xlink:href="http://imgcache.gtimg.cn/club/pgg/ams/img/pkcard_placeholder.png" width="100%" height="100%" /> </mask> <rect x="0" y="0" width="100%" height="100%" fill="#00A5E0" mask="url(#maskId)" /> </svg>[ svg mask ]
3. svg的蒙版mask-type
可以看到,基于svg 的mask屬性,可以生成一塊用于切割倒計時動畫的遮罩層。但是有些地方是半透明的是怎么回事,實際上svg的mask屬性,其遮罩類型是luminance,也就是基于亮度來進行遮罩的。因此只需要把mask的mask-type設(shè)置為基于透明度就可以了mask-type='alpha':
<mask id="maskId" patternUnits="userSpaceOnUse" mask-type="alpha"> <image x="0" y="0" xlink:href="http://imgcache.gtimg.cn/club/pgg/ams/img/pkcard_placeholder.png" width="100%" height="100%" /> </mask>
[ mask-type='alpha' ]
基于以上的倒計時效果和蒙版遮罩層,再設(shè)置circle上面的stroke屬性的顏色值為rgba(0,0,0,.5),就可以實現(xiàn)半透明的遮罩層。綜合上面的倒計時效果,就可以實現(xiàn)想要的半透明不規(guī)則倒計時效果。
由于為了把circle的倒計時起點設(shè)置為頂部,加了類transformNe90旋轉(zhuǎn)了90度,因此在圖形遮罩層上,需要設(shè)置類transform90實現(xiàn)反方向90度的旋轉(zhuǎn):
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <mask id="maskId" patternUnits="userSpaceOnUse" mask-type="alpha"> <image x="0" y="0" xlink:href="http://imgcache.gtimg.cn/club/pgg/ams/img/fushenka2.png" width="100%" height="100%" class="transform90"/> </mask> <image x="0" y="0" xlink:href="http://imgcache.gtimg.cn/club/pgg/ams/img/fushenka2.png" width="100%" height="100%"/> <circle class="transformNe90" cx="50%" cy="50%" r="50%" stroke-width="100%" stroke="rgba(0,0,0,.5)" fill="none" stroke-dasharray="628.32 628.32" mask="url(#maskId)"> <animate attributeType="XML" attributeName="stroke-dasharray" from="0" to="628.3" dur="10s" fill="freeze" repeatCount="10"></animate> </circle> </svg> <style> .transform90 { transform: rotate(90deg); transform-origin: center center; } .transformNe90 { transform: rotate(-90deg); transform-origin: center center; } </style>
[ 不規(guī)則倒計時動效 ]
基于以上的實現(xiàn),已經(jīng)實現(xiàn)了一個固定長寬,固定圖,固定透明度的不規(guī)則倒計時效果,但是在實際的應(yīng)用中,我們需要兼容各種不同尺寸的圖形,因此需要把它抽象成組件,支持設(shè)置image的src、height、width以及circle的dur、from等屬性
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" :width="width" :height="height" :viewbox="'0 0 ' + width + ' ' + height" class="pk-countdown" > <defs> <mask :id="maskId" patternUnits="userSpaceOnUse"> <image x="0" y="0" width="100%" height="100%" class="transform90" :xlink:href="src" /> </mask> </defs> <image x="0" y="0" :xlink:href="src" width="100%" height="100%" /> <circle cx="50%" cy="50%" r="50%" stroke-width="100%" :stroke="'rgba(0,0,0,' + opacity + ')'" fill="none" :stroke-dasharray="'0 ' + circle" :mask="'url(#'+maskId+')'" class="transformNe90" > <animate attributeType="XML" attributeName="stroke-dasharray" :from="circleStart" :to="circle" :dur="duration + 's'" fill="freeze" :repeatCount="repeatCount" /> </circle> </svg> ... circleStart() { return (this.process / this.duration) * this.circle }, circle() { return (Math.PI * 2 * Math.max(this.width, this.height)) / 2 }這樣就可以通過父組件傳遞屬性,控制倒計時效果的各種屬性,實現(xiàn)通用的不規(guī)則倒計時效果。
svg是一個很強大的矢量圖繪制工具,可以直接內(nèi)嵌到網(wǎng)頁的dom中,并且可以通過css設(shè)置svg的各種屬性,相對于canvas,它的操作更加靈活,實現(xiàn)更加簡單。結(jié)合svg的mask和filter等屬性,可以實現(xiàn)很多酷炫的效果。而且它的兼容性好,基本主流的瀏覽器都支持,還兼容到IE9,對于需要用css實現(xiàn)的復(fù)雜效果,都可以考慮用svg實現(xiàn)。
附圖:
[ svg兼容性 ]
總結(jié)
以上是生活随笔為你收集整理的卡牌特效: svg不规则倒计时动效的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 直播预告│据说这是人工智能领域里最难的一
- 下一篇: GIAC | 大数据分析系统在游戏领域的