寫在前面
之前有提到過 SVG 描邊動畫,可以實現很神奇的手寫簽名動畫效果,當然,理論上可以用來實現任意不規則路徑填充動畫
在支持 SVG 的場景,可以考慮採用強大的 SVG 描邊動畫,能夠實現一些 incredible 效果,在處理不規則描邊、填充動畫方面療效確切
一。兼容性
SVG(Scalable Vector Graphics)是一種基於 XML 的標記語言,用來描述二維矢量圖
基礎兼容性(Can I use SVG):
桌面 [IE9+]
移動 [Android4.4+] [Android3-4.3] 部分支持
SVG 動畫元素兼容性(Can I use SVG animation):
移動 [Android3+] iOS[6.1+]
在移動端早就可以隨便玩了,比如用 animateMotion 實現沿不規則路徑運動效果
二。應用場景
1.icon
iconfont 兼容性確實比 SVG 好,但有一些限制:
-
只支持 font 相關的 CSS 規則
-
瀏覽器對字體的優化(抗鋸齒等等),導致不同瀏覽器下 icon 顯示效果有差異
-
依賴字體文件,糟糕情況(下載失敗,或者用戶偏好自定義字體)下,會顯示框框,甚至與 emoji 衝突
只能純色或者漸變,而且大小定位受 line-height, vertical-align, letter-spacing 等影響,實際尺寸可能存在偏差(很難對齊)
SVG icon 的優勢:
-
矢量圖,隨便縮放
-
可以控制 icon 不同部分的樣式,描邊��色等等
-
實際尺寸精確,佔據空間與 SVG 元素尺寸一致
-
糟糕情況下,可以用 png 做平滑 fallback
關於 SVG icon 的更多信息,請查看:
2. 動畫
SVG 結合 animation 能夠實現很多神奇的效果:
-
不規則描邊動畫(手寫簽名)
-
填充動畫(手繪)
-
不規則路徑動畫(讓元素沿不規則路徑運動)
一個印象深刻的 SVG 動畫:Animated line drawing in SVG,更多 SVG 動畫案例見 30 Awesome SVG Animation For Your Inspiration
3. 圖表
一些很受歡迎的圖表庫都採用 SVG 來實現,例如 d3、google charts 等等
相比 canvas 圖表,SVG 圖表在過渡動畫方面有先天優勢,能夠實現很漂亮的過渡效果,例如 D3 Tree
三。SVG 元素
SVG 有一套自己的元素定義(與 HTML 元素類似),用來描述二維圖形。用 svg 標籤包裹起來,可以直接嵌入 HTML 中,例如:
<h3>svg demo</h3>
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="30" height="30"></rect>
</svg>
<span>sibling</span>
顯示 30x30px 的黑方塊,svg 元素尺寸為 100x100px,svg 元素默認 display: inline,所以 "sibling" 文本與黑方塊並列
P.S.width, height, x, y 等屬性不帶單位的話,默認是 px,也可以帶 em, ex, in, cm, mm, pt, pc, % 等單位
SVG 元素比較多,且與 HTML 元素有交集,見 SVG element reference
1. 形狀元素
基本形狀有 6 種:<circle>, <ellipse>, <line>, <polygon>, <polyline>, <rect>,另外 <path> 可以用來定義任意形狀,包括 4 中基本形狀
rect
<rect x="50" y="10" width="30" height="30" rx="5" ry="5"></rect>
其中 rx, ry 用來定義圓角,分別表示四角的橢圓在 x 軸、y 軸方向的半徑。當然,用圓角畫圓的技巧仍然適用:
<rect x="50" y="10" width="30" height="30" rx="50%" ry="50%"></rect>
x, y 表示左上角的坐標,坐標系與 canvas 2d 相同,左上角為 (0, 0)
circle
<circle cx="150" cy="25" r="15"></circle>
cx, cy 表示圓心位置
ellipse
<ellipse cx="200" cy="30" rx="25" ry="20"></ellipse>
rx, ry 分別表示 x 軸方向半徑和 y 軸方向半徑
line
<line x1="250" y1="10" x2="300" y2="30" style="stroke: black"></line>
注意,默認沒有描邊,看不見線,這裡用 stroke 設置描邊顏色
polygon
<polygon points="60,50 100,70 100,110 60,130 20,110 20,70"></polygon>
給定一組點,畫出閉合多邊形
polyline
<polyline points="150,50 190,70 190,110 150,130 110,110 110,70" style="fill: none; stroke: black"></polyline>
與多邊形類似,折線不自動連接首尾
注意,默認填充黑色且沒有描邊,與上例多邊形沒有任何區別,這裡用 fill 去掉填充色,用 stroke 添上黑色描邊
2. path
通用形狀定義,可以用來實現上面提到的所有形狀,例如:
<path d="M 10 10 L 100 10 L 100 80 Z" style="fill: orange; stroke: black; stroke-width: 1"></path>
一個帶黑色描邊用橘黃色填充的直角三角形,屬性 d 表示一系列路徑描述,包含一些指令:
Moveto M 提筆到
Lineto L 畫直線到
H 畫水平直線到
V 畫豎直直線到
Curveto C 畫三次貝塞爾曲線到(需要提供 2 個控制點)
S 與上一條三次貝塞爾曲線連起來(只需要提供第二個控制點和終點,第一個控制點是上一條曲線的第二個控制點的對稱點)
Q 畫二次貝塞爾曲線到(需要提供 1 個控制點)
T 與上一條二次貝塞爾曲線連起來(只需要提供終點,控制點是上一條曲線控制點的對稱點)
Arcto A 畫橢圓曲線到
ClosePath Z 直線連接當前點和起點
注意,用 Z/z 閉合路徑,與手動 L 起點 不同,因為閉合指令會讓把線段端點拼接起來
各指令具體用法:
M x,y 絕對坐標
m dx,dy 相對坐標
L/l 同上
H/h 同上
V/v 同上
C/c c1x,c1y c2x,c2y x,y 控制點 1 控制點 2 終點
S/s cx,cy x,y 控制點 2 終點
Q/q cx,cy x,y 控制點 終點
T/t x,y 終點
A rx,ry xAxisRotate LargeArcFlag,SweepFlag x,y
x,y 方向半徑 x 軸與水平軸順時針夾角 [1/0] 大/小角度弧線 [1/0] 順/逆時針到終點 終點
Z/z 無參,Z 和 z 沒有區別
例如:
<!-- 矩形 -->
<path d="M 10 10 H 70 80 V 70 80 H 10 10 z" style="stroke: black"></path>
<!-- 三次貝塞爾曲線 -->
<path d="M 10 10 C 30 40 90 60 30 100 S 50 50 150 10 S 100 130 100 120" style="fill: none; stroke: black"></path>
P.S. 關於 d 屬性的更多信息,請查看:
3. 文本
<text x="100" y="40" dx="10" dy="10" text-anchor="middle" rotate="10 10" style="font-family: Consola monospace; font-size: 24px; stroke: skyblue; fill: pink;">
SVG text styling
</text>
x, y,dx, dy 用於定位,前者絕對定位,後者相對自身偏移,text-anchor 用來定位文本(相對 x, y 左/右/居中對齊)
注意:rotate 屬性很神奇,與 style="transform: rotate(10deg);" 整體旋轉不同,rotate 屬性是針對字符(glyph)的,可以傳入一組值,按順序分別作用於各個字符,所以可以用來實現類似於斜體的效果
P.S. 關於 rotate 屬性的更多信息,請查看 Chapter 11: Text
4. 樣式
除了 CSS 支持的樣式屬性,SVG 還支持一些特有的,例如 stroke、fill 等等,常見的如下:
fill 填充色,文本顏色也由該屬性控制
stroke 描邊顏色
stroke-width 描邊寬度
stroke-linecap 端點樣式,圓角,直角等等,與 canvas 一致,butt | round | square
stroke-dasharray 虛線樣式
也可以通過 CSS 選擇器對 SVG 元素應用樣式,例如:
<style>.line {stroke: red;}</style>
<svg>
<line class="line" x1="10" y1="10" x2="100" y2="80"></line>
</svg>
但 SVG 裡的 style 元素與 HTML 的不同,上面的方式等價於:
<svg>
<style><![CDATA[
.newLine {stroke: red;}
]]></style>
<line class="newLine" x1="10" y1="10" x2="100" y2="80"></line>
</svg>
把樣式規則用 CDATA 包起來是為了避免 XML 解析出錯:
Note how the CSS style sheet is placed within a CDATA construct (i.e., ). Placing internal CSS style sheets within CDATA blocks is sometimes necessary since CSS style sheets can include characters, such as ">", which conflict with XML parsers. Even if a given style sheet does not use characters that conflict with XML parsing, it is highly recommended that internal style sheets be placed inside CDATA blocks.
(引自 Styling-SVG 1.1(Second Edition))
5. marker
marker 標記能貼附在圖形元素上,例如用 marker 來添箭頭:
<defs>
<marker id="Triangle" viewBox="0 0 10 10" refX="1" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" />
</marker>
</defs>
<path d="M 10 10 C 50 80 40 20 120 50" fill="none" stroke="black" stroke-width="1" marker-end="url(#Triangle)"></path>
通過 defs 來定義可復用的元素,通過 id 來引用之前定義的 marker 元素,url(#Triangle) 叫 Functional IRI reference
這裡定義了一個箭頭,並添到路徑曲線的終點處,可選位置為:
marker-start 起點
marker-mid 各個中間點
marker-end 終點
marker 各屬性含義如下:
viewBox 坐標系區域
refX/Y 參照點,繪製時該點與端點重合
markerUnits 定義坐標系單位 userSpaceOnUse 當前坐標系單位 | strokeWidth 線寬(默認)
markerWidth/Height 標記寬高,默認值為 3
orient 繪製方向,值為 auto 或角度值
默認 markerUnits="strokeWidth" 根據圖形線寬自適應 marker 尺寸,如果 markerUnits="userSpaceOnUse" 的話,指定 marker 單位為當前坐標系單位,不會相對圖形線寬調整
默認 orient="auto" 自動計算朝向角度,曲線上的箭頭指向斜率方向,非常精細自然
P.S. 關於 marker 的更多信息,請查看 11 Painting: Filling, Stroking and Marker Symbols
6. 濾鏡
通過應用 filter 來改變渲染效果,讓顯示效果更好。使用方式與 marker 類似:
<defs>
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
</filter>
</defs>
<path d="M 10 20 C 50 80 40 20 120 60" fill="none" stroke="black" stroke-width="1" filter="url(#blur)"></path>
通過 feGaussianBlur 元素定義高斯模糊濾鏡(毛玻璃效果),並設置模糊程度參數 stdDeviation,in 用來設置應用濾鏡的對象,這裡 SourceGraphic 表示原圖,也可以只對 alpha 通道或者背景圖片(應用濾鏡的整片區域快照)應用
此外還支持陰影、光照、顏色等濾鏡,具體信息請查看 SVG element reference
7. 漸變
支持線性漸變和放射性漸變,用法與 marker 類似,例如:
<defs>
<linearGradient id="linear" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#000"/>
<stop offset="100%" stop-color="#fff"/>
</linearGradient>
<radialGradient id="radial">
<stop offset="10%" stop-color="#eee"/>
<stop offset="95%" stop-color="#ccc"/>
</radialGradient>
</defs>
<rect x="0" y="0" width="100%" height="50%" fill="url(#linear)"></rect>
<rect x="0" y="50%" width="100%" height="50%" fill="url(#radial)"></rect>
分別定義了純黑到純白的豎直線性漸變、中心亮周圍漸暗的放射性漸變
四。在線 Demo
上文提到的所有示例:http://www.ayqy.net/temp/svg/svg.html
暫無評論,快來發表你的看法吧