這是在作一個呼吸燈動效時遇到的問題,就是如何給SVG的圖形元素加上一些陰影的效果,好比外發光,好比內發光,好比投影,以前也有困擾,可是由於沒到非解決不可的程度,因此就暫時擱置了。對於發光這種效果,對於CSS3來講,很簡單的事情,一個box-shadow屬性能夠解決全部問題,我曾經寫過一篇關於CSS3樣式的文章UI設計師進階技能——CSS3之樣式篇裏枚舉的很是全面,包括各個參數如何去和PS一一對應,不但能設置是外陰影仍是內陰影,尺寸,X和Y的偏移,還能夠多種效果去疊加,玩好了,當成是畫圖神器都是有可能的。css
這是直接給一個100*100的div盒子定義了外發光後的效果,爲了方便修改顏色,用了hsla的色值表示方法。html
#box{
height:100px;
width:100px;
background: hsla(168,90%,45%,1);
border-radius: 50px;
box-shadow:0 0 70px hsla(168,90%,45%,1);
}
複製代碼
一個完美的外發光效果,試一下將box-shadow屬性定義到動畫規則中,會發生什麼:動畫
/*定義一個透明度變化(hsla的a值改變)動畫規則*/
@keyframes outLight{
0%{box-shadow:0 0 70px hsla(168,90%,45%,1)}
100%{box-shadow:0 0 70px hsla(168,90%,45%,0.1)}
}
#box {
height:100px;
width:100px;
background: hsla(168,90%,45%,1);
border-radius: 50px;
animation: outLight 1s ease infinite;
}
複製代碼
能夠輕鬆實現這種透明度變化產生的「砰砰」動效。那再試一下改顏色,爲了少寫一個動畫規則,我先不給盒子填充任何背景顏色,僅保留box-shadow效果。之因此用hsla色值表示方法,也是爲了調整顏色方便,只要改一下h值就能夠了。ui
/*定義一個顏色變化(hsla的h值改變)動畫規則*/
@keyframes outLight{
0%{box-shadow:0 0 70px hsla(168,90%,45%,1)}
100%{box-shadow:0 0 70px hsla(220,90%,45%,1)}
}
#box {
height:100px;
width:100px;
border-radius: 50px;
animation: outLight 0.7s linear alternate infinite;
}
複製代碼
變色也很OK,其餘值的改變就再也不作嘗試了。url
這裏我試着作了一排依次按順序點亮的信號燈效果,任意一個時刻都是四個不一樣的顏色。spa
這裏,我若是想作一個圓環的外發光效果,抱歉,box-shadow屬性告訴你,這是天方夜譚,由於字面意思來說,box——盒子,做爲盒子模型,支持的是一個總體的外觀,或者稱之爲邊緣效果。設計
drop-shadow
確切來講是濾鏡filter
的一種,還有常見的模糊濾鏡blur,黑白濾鏡grayscale等等,此次先只說這個投影。語法簡單:3d
.box {
height:100px;
width:100px;
border-radius:50px;
/*filter:drop-shadow 濾鏡*/
filter: drop-shadow(0 0 30px hsla(168,90%,45%,1));
background-color: hsla(168,90%,45%,1);
}
複製代碼
也能夠獲得一個完美的外發光效果,但這裏有個很大的坑,就是會受元素填充顏色的影響,好比,改掉背景顏色的透明度background-color: hsla(168,90%,45%,0.2)
,會發現投影效果也會發生變化。code
drop-shadow
濾鏡是不像box-shadow
屬性那樣支持多個設置疊加的,由於畢竟filter
纔是屬性,因此投影的濾鏡只能設置一個。可是,濾鏡由於是加給實體的,不受什麼盒子模型影響,因此,當個人盒子是一個描邊而非填充樣式時cdn
filter: drop-shadow(0 0 8px hsla(168,90%,45%,1));
border:10px solid hsla(168,90%,45%,1);
複製代碼
就能獲得一個內外發光的圓環了。
這個搭配SVG可謂無往不利,好比,想給下面這種複雜的SVG圖形加一個投影,直接讓SVG使用定義好的濾鏡就能夠了。
原本就是一個普通平面的SVG圖形,加了filter="drop-shadow(0 10px 5px hsla(168,0%,45%,0.4))"
的定義後,瞬間躍然紙上。並且投影的邊緣徹底就是圖形的邊緣,這但是box-shadow
屬性無能爲力的事情。
來試一下對動畫的支持。
/*定義一個投影效果透明度變化(hsla的a值改變)動畫規則*/
@keyframes outLight{
0%{filter: drop-shadow(0 0 10px hsla(168,90%,45%,1))}
100%{filter: drop-shadow(0 0 10px hsla(168,90%,45%,0.1))}
}
複製代碼
依然能夠獲得動效。變色就不作了,也是支持的。
如今,新的需求又來了,我要給SVG中的圖形元素加投影,首先聲明,單個圖形元素是不支持使用drop-shadow濾鏡屬性的,已經踩過這個坑了,那還有救沒?有。
上面的投影濾鏡是CSS的filter屬性,只能把SVG當成一個圖片元素總體來處理,終極目標來着,SVG+CSS3的動畫對不對?這須要把SVG裏面的圖形元素單獨屬性賦值。SVG強大的<def>
元素可讓這一切都變成現實。咱們要作的就是,首先定義一個id爲outLight濾鏡,語法以下:
<defs>
<filter id="outLight">
<!-- 定義了一個水平和垂直偏移距離爲0,大小爲10的外發光效果 -->
<feDropShadow dx="0" dy="0" stdDeviation="10" flood-color="hsla(180,90%,40%,0.9)" />
</filter>
</defs>
複製代碼
這裏有一些特殊的語法,dx和dy經過字面意思容易理解,就是水平和垂直的偏移距離,steDeviation是個什麼屬性?來看一下MDN文檔中對steDeviation的官方解釋:
The stdDeviation attribute defines the standard deviation for the blur operation.
用句簡單的話來解釋,就是投影的尺寸。
顏色的定義,屬性名爲flood-color,一樣,若是不hsla或者rgba這種自帶透明度定義的色值表示方法,須要調節透明度的話,則經過flood-opacity屬性來定義。
我使用了一個描邊的圓形經過filter:url(#outLight)
語句來調用這個濾鏡,效果卻並不理想:
外發光效果的實現沒有問題,但很明顯的看出彷佛濾鏡做用的區域被截取了。追本溯源來找緣由,關於<filter>
濾鏡的屬性值這樣寫道:
The position and dimensions of a filter may be specified using the following parameters: x, y, width, height. The default values are:
- x: -10%
- y: -10%
- width: 120%
- height: 120%
簡而言之,就是濾鏡默認做用範圍爲使用元素溢出10%,在上面這個案例中,由於發光的範圍較大,顯然10%的溢出是不夠的,既然默認值不合理,那就從新定義一下
<filter id="outLight" x="-50%" y="-50%" width="200%" height="200%">
複製代碼
這樣的話,我給到了200%的溢出範圍,這樣就解決了外發光半徑超出默認做用區域的問題。
獲得完美的外發光圓環。
能夠隨隨便便修改dx和dy的值,好比下面這種:
甚至讓投影徹底脫離本體
filter
濾鏡還能作什麼在深刻了解濾鏡以前,我一直把SVG定位爲矢量圖形,結合最多的也是平面風格的插畫,但當祭出濾鏡神器,忽然發現,能夠用SVG來讓純色填充的圖形變得有質感,好比增長紋理,好比增長浮雕效果。
下面這張圖片這樣看真的是平淡無奇,這是我在AI中繪製的基礎圖形。
燃鵝,當我按照下面圖層拆分後依次加上對應的濾鏡效果後
)下面,就是見證奇蹟的時刻:
瞧這凹凸有致浮雕效果,瞧這底部細膩的紋理,是否是很難想象,在SVG中不過是下面這兩句濾鏡定義來實現的:
<!-- 給底層增長噪點效果的濾鏡 -->
<filter filterUnits="objectBoundingBox" id="noise">
<feTurbulence baseFrequency="0.5" id="c2" in="c1" numOctaves="10" result="c2" stitchTiles="noStitch" type="fractalNoise">
</feTurbulence>
<feComposite in="c2" in2="SourceAlpha" operator="in"></feComposite>
</filter>
<!-- 模糊濾鏡 頂部高光和底部陰影均可以使用 -->
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
</filter>
複製代碼
放幾個最終的效果來show一下技巧:
旋轉效果
閃爍效果:
關於<filter>
深刻了解的話,應該有意思的地方還有不少,目前我能徹底弄明白只有投影和模糊,等徹底搞清楚以後,會來一篇單獨介紹濾鏡的專題。由於投影能夠徹底follow本體的變化,好比隨便來個最簡單的縮放:
另外關於利用濾鏡作動效的創意,還在左思右想中,這又是另一篇了。
- 經過
<defs> <filter><feDropShadow ……/> </filter> </defs>
的語法來定義一個投影效果的濾鏡。- 默認
<filter>
的做用範圍爲10%的溢出,當投影尺寸大時,須要修改x、y、width、height的值。