SVG 隨便學學就會了
這兩天閑來沒事把 Echart 換成 Rechart 感覺世界都清爽了。因為 rechart 使用 svg 來渲染,所以順帶學了下 SVG 感覺很輕松哦。
概念
SVG 是 w3c 的退出的規范。(就是 w3c 指定語法。各大廠商自己去實現)。SVG 渲染的是矢量圖(它之規定了圖像怎么畫,而不是規定那個像素畫什么顏色)。
優點
因為以上兩點(w3c, 矢量圖)所以他有兼容性好,不失真的優點。除此之外還有:
使用xml的格式規范(HTML 也是)。在瀏覽器上基本上可以看做是DOM節點來操作。(事件,渲染樣式)
svg 不同於位圖指定每一個像素的渲染,內部其實是用簡介的語法指定圖應該從哪畫到那怎么畫。本質上就是文本,所以很小。
這些優點決定了他很適合在前端畫一些簡單的圖。(畫復雜的就算了交給設計師吧)
Getting Started
在現在的瀏覽器使用 SVG 太簡單不過了。只需要在HTML中直接寫
<!-- version prop in svg will be Deprecated -->
<!-- xmlns is unnecessary for inner svg elements or inside HTML documents. -->
<svg width="100" height="100">
<line x1="0" y1="0" x2="100" y2="100" stroke="red"></line>
</svg>
- 可以清楚的看到 svg 的語法。svg 是 xml 的語法格式。svg 是定義一個容器。其定義一個圖的大小。圖的內容由其子元素來確定。
<svg> props
- width | height 定義元素的大小
與 canvas 不同,width 和 height 是定義一個類似於窗口的顯示大小,可以在窗口外畫東西,只是你一般看不到。可以是svg顯示這個寬口外的圖,后面講。
svg 子元素
畫圖總離不開一些簡單的圖形,svg 對這些進行了封裝,成為以下的標簽。
<line x1="2" y1="4" x2="4" y5="7"></line>: 兩點確定一條線段,x1,y1,x2,y2 就是指定這兩個點的。
<rect x="2" y="4" width="100" rx="4" ry="4" height="100"></rect>: 畫長方形的,需要注意的是rx ry 是用來畫帶圓角的長方形的。就像css的border-radius;
<circle cx="13" cy="13" r="40"></circle>:cx, cy 確定圓心,r為半徑畫一個圓。
<ellipse cx="0" cy="0" rx="132" ry="test"></eliipse>: 這個是畫橢圓,rx, ry 是定義橢圓的x半徑, y軸半徑的。
<polygon points="0,0 3,3 4,4"></polygon>: 等價於你拿着筆按順序畫過經過的 points 中的各個點,最后回到第一個點。圍起來的圖形。
--- 以上就是一些常用的簡單圖了 ---
曲線(最復雜)
這個是普通 HTML CSS 沒辦法做到的。所以這個是學 SVG 中最高性價比的東西。
直接上例子
<!-- 畫一條從(0,0)到(50,50)的線 -->
<svg width="100" height="100">
<path d="M0 0 L50 50"></path>
</svg>
可以看到標簽是path,d為屬性。屬性d的值使用 Commandx y 這樣的語法格式。(注意Command后直接跟參數沒有空格)
| 指令 | 參數 | 說明 |
|---|---|---|
| M | x y | 將點移動到 (x,y) 經過不划線 |
| L | x y | 將點移動到 (x,y) 並划線 |
| H | y | 將點的y坐標做變化x不變,並划線 |
| V | x | 將點的x坐標做變化y不變,並划線 |
| 說明 | x,y | 上面的參數都是絕對值,線面都是相對值 |
| m | 參數都一樣 | 將點的個個坐標都添加上x,y的值,作用跟M一樣 |
| l | 參數都一樣 | 將點的個個坐標都添加上x,y的值,作用跟L一樣 |
| h | 參數都一樣 | 將點的個個坐標都添加上x的值,作用跟H一樣 |
| v | 參數都一樣 | 將點的個個坐標都添加上y的值,作用跟V一樣 |
| z | 沒有參數 | 將點移動到起點,並划線 |
(媽媽(M)拉(L)我看湖(H)南衛(V)視。真是智(Z)障。
下面真的搞曲線了
接觸過曲線的都知道貝塞爾曲線,SVG 畫曲線也玩不出花來肯定是用貝塞爾曲線的。
<svg width="100" height="100">
<path d="M0 0 Q0 100, 100 100"></path>
<svg>
畫貝塞爾曲線一般需要3個參數,但是畫圖的語言,一般會記錄上一個點,所以SVG的命令就是 Qx y,targetX targetY。
| 指令 | 參數 | 說明 |
|---|---|---|
| Q | x y,targetX targetY | 以(x, y)為切點,上一個點位起點,(targetX, targetY)為終點畫一條貝塞爾曲線 |
| T | targetX targetY | 以上條貝塞爾曲線的弧度畫一條到(targetX, targetY)的貝塞爾曲線,如果上一條划線不是貝塞爾那就是畫一條直線 |
騰訊QT語音的兩個字的靈感不會是從這里來的吧。
當然還有三次貝塞爾曲線的。語法類似。
| 指令 | 參數 | 說明 |
|---|---|---|
| C | x y, x2 y2,targetX targetY | 以(x, y),(x2,y2)為3次貝塞爾的曲線參數,上一個點位起點,(targetX, targetY)為終點畫一條貝塞爾曲線 |
| S | targetX targetY | 類比上一個 |
用QT語音打CS????
樣式的定義
SVG畫的線部分已經結束了,接下來我們上色,跟描邊。
上面的全部標簽都可以分為兩部分,一部分是線,已經線包圍起來的內容。
線的樣式可以在標簽上用stroke來定義, 包圍起來的內容用fill。
- stroke 有 stroke stroke-width stroke-linecap stroke-opacity等
- fill 有 fill fill-opacity fill-rule 等
<svg width="100" height="100">
<circle
width="100" height="100" x="0" y="0"
stroke="red" stroke-width="2" stroke-linecap="round" stroke-opacity="0.8" stroke-linejoin="round"
fill="green" fill-opacity="0.8"
></circle>
</svg>
圖形的復用
就這么老老實實的搬一般就夠用了,但是這程序最重要的就是少搬磚,多偷懶。
有時候我們可能一個圖中有了很多個相同的圖,這時候就copy就慘了。偷懶第一招。
<svg width="100" height="100">
<defs>
<g id="ahole">
<rect x="0" y="0" width="50" height="50" id="rect1"></rect>
<circle
width="100" height="100" x="0" y="0"
stroke="red" stroke-width="2" stroke-linecap="round" stroke-opacity="0.8" stroke-linejoin="round"
fill="green" fill-opacity="0.8"
id="circle1"
></circle>
</g>
</defs>
<use href="#ahole"/>
<use href="#rect1" x="123123"/>
<!-- you can add any props you want to replace the svg element you used -->
<use href="#circle1" y="123123"/>
</svg>
解析:defs 就是定義聲明不會在svg中划出。g是將其子元素統統打包,方便use的時候使用。use 就是調用啦,通過href:#id的方式來指定使用哪一個小圖形,你可以在use的標簽中使用任何屬性來替掉你use的標簽原來的屬性。這里要說明,use 不一定只能應用 defs 中定義的,只要在上下文前,有用id命名的都可以。
偷懶第二招
上面這招只能在同一個svg中使用,但是我們想在每一個svg中使用呢。比如UI庫中的icon可能有大量的svg,這是用引用一個就畫一個svg顯然有點浪費。
<svg style="display: none;">
<symbol id="beaker">
<!-- <path>s and whatever other shapes in here -->
<rect width="40" height="100" x="0" y="0" fill="red"></rect>
</symbol>
</svg>
<svg width="100" height="100" style="border:solid 1px green">
<use href="#beaker"></use>
</svg>
解析:把包含symbol的svg隱藏,並注入大量要使用的svg圖,后面的svg就可以簡單的通過use來應用了。(這里的svg版本都是最新的,以前版本的語法可能需要xmlns:href等復雜的寫法,我選擇擁抱最新)
與CSS的結合
我們可以通過給svg元素添加class,並在 css 中設置樣式。
<css>
.rect {
fill: green;
x: 20px;
}
</css>
<svg fill="red">
<rect x="0" y="0" width="100" height="100" class="rect"></rect>
</svg>
個人建議:css 雖然可以設置定位的屬性,但是最好還是不要使用定位,不然維護起來會很麻煩,盡量只是用css來定義顏色樣式。另外結合 css3 的 transform 和 animation 能實現很好的動畫效果。
總結: 入門款就是這個樣子了,后面有時間再跟新進階版。包括 preserveAspectRatio filter text 動畫等知識。
