SVG 初探

最近看到一篇頗有趣的關於動畫的文章,想拿來作個練習,裏面用到了SVG,因此花了一些時間瞭解了一下SVG,在這裏作一個記錄,方便自查git

全部文章均同步到個人博客github

SVG是神馬?

  • SVG指可伸縮矢量圖
  • 用來定義基於矢量的網絡圖形
  • 使用XML格式來定義
  • 在放大或縮小的狀況下,圖形質量不受影響
  • 在2013年成爲W3C推薦標準
  • 瀏覽器支持狀況:IE9+,chrome 33.0+,Firefox 28.0+,Safari 7.0+

SVG使用方式

瀏覽器直接打開

.svg文件直接用瀏覽器打開chrome

在HTML中使用

<iframe>嵌入SVG瀏覽器

<iframe src="xx.svg" width="200" height="200" ></iframe>

<img>嵌入SVG網絡

<img src="xx.svg"  width="300" />

用CSS背景圖的方式嵌入SVGapp

div {
    background: url('xx.svg') no-repeat center;
    background-size : 200px 200px;
}

直接使用<svg>元素svg



<svg width="600px" height="300px" viewBox="0 0 250 250"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/> <rect x="150" y="50" width="200" height="100" style="stroke: blue; fill: none;"/> <svg x="150px" y="50px" width="200px" height="100px" viewBox="0 0 125 125" preserveAspectRatio="xMaxYMax meet"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: rgba(0,0,0,.5);"/> </svg> </svg>

後面還有兩種embed和object方式,不建議使用,就不作介紹了。工具

經常使用<img><svg>,作背景圖時用background-image引入動畫

SVG結構

.svg文件

常見寫法:url

<?xml version="1.0"?> //XML聲明
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="300">
    <!-- SVG代碼 -->
</svg>
//xmlns="http://www.w3.org/2000/svg"是聲明空間

直接在HTML中使用<svg>



<svg width="600px" height="300px" viewBox="0 0 250 250"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: none;"/> <rect x="150" y="50" width="200" height="100" style="stroke: blue; fill: none;"/> <svg x="150px" y="50px" width="200px" height="100px" viewBox="0 0 125 125" preserveAspectRatio="xMaxYMax meet"> <circle cx="35" cy="35" r="35" style="stroke: black; fill: rgba(0,0,0,.5);"/> </svg> </svg>

注意不用再寫XML聲明瞭。

SVG圖形、屬性及基本操做

基本圖形

  • 矩形<rect>
  • 圓形<circle>
  • 橢圓<ellipse>
  • <line>
  • 折線<polyline>
  • 多邊形<polygon>
  • 路徑<path> 後面會重點介紹

基本屬性

  • fill 填充顏色(rgb 值、顏色名或者十六進制值)
  • stroke 定義圖形邊框的顏色
  • stroke-width 定義圖形邊框的寬度
  • transform 聲明自身座標相對父級座標系的變換,很重要的屬性,後面會深刻探討

基本操做

  • 建立圖形,document.createElementNS(ns, tagName), ns是svg的命名空間
  • 添加圖形,element.appendChild(childElement)
  • 設置/獲取屬性,element.setAttrbute(name, value)element.getAttribute(name)

好比:

var SVG_NS = 'http://www.w3.org/2000/svg';
var svg = document.createElementNS(SVG_NS, 'svg');
svg.setAttribute('width', '100%');
svg.setAttribute('height', '100%');
document.getElementById('svg-wrap').appendChild(svg);

座標系統

重點來了,SVG的座標系統

首先介紹一下SVG兩個很重要的概念:viewport,viewBox

viewport

viewport,也能夠叫作視窗,表示SVG可見區域的大小,超出這個區域的圖形將不被顯示出來,至關於將要做畫的畫板大小,在<svg>中經過widthheight來控制SVG的viewport的大小,注:若不加單位,則默認爲px

<svg width="400" height="200" style="border:1px solid #7798CB">
    <rect x="30" y="10" width="30" height="15" fill="#5CC26F" />
</svg>

效果以下,在svg可視區範圍內,也就是viewport裏的座標爲(30,10)的地方放了一個綠色矩形:

svg-viewport

viewBox

viewBox, 也能夠叫視野,這個矩形區域定義了咱們要如何去觀看svg在viewport上渲染出來的世界,借用張鑫旭大神的一個很好的比喻:「SVG就像是咱們的顯示器屏幕,viewBox就是截屏工具選中的那個框框,最終的呈現就是把框框中的截屏內容再次在顯示器中全屏顯示」。這個在地圖裏應用很普遍,相似百度地圖,谷歌地圖,滑動滾輪就可讓地圖放大縮小的效果。

說了這麼多,仍是動手寫幾個例子來體會一下,其中viewBox="x(左上角橫座標), y(左上角縱座標), width, height"

<svg width="400" height="200" viewBox="0,0,400,200" style="border:1px solid #7798CB">
    <rect x="30" y="10" width="30" height="15" fill="#5CC26F" />
</svg>

效果以下:

svg-viewbox1

由於viewBox的寬高和svg的同樣,至關於我透過跟svg同樣大的窗戶去看svg的世界,因此效果沒有任何變化

修改一下viewBox的寬高

<svg width="400" height="200" viewBox="0,0,40,20" style="border:1px solid #7798CB">
    <rect x="30" y="10" width="30" height="15" fill="#5CC26F" />
</svg>

svg-viewbox2

這時,咱們看到svg裏面的小矩形跑到了svg邊框的右下角,同時還被放大到300*150,超出svg的部分不顯示,有木有感覺到viewBox的巨大威力~~

這裏爲啥小矩形會被「挪到」右下角呢,這是由於viewBox的大小是40*20,並且從座標(0,0)處開始,而rect的座標是(30,10),那麼我用viewBox去圈viewport的時候,rect就會出如今viewBox的右下方。專門作了一張圖,幫助理解

svg-viewbox3

上圖比較形象的解釋了小矩形的變化,接着將viewBox在viewport裏全屏展現,這時rect的寬高會10倍放大,由於viewBox和viewport的width比例和height比例都是1/10,同時viewBox的寬高比和viewport的寬高比一致,都是2/1,那麼rect的寬高都會放大10倍。

這是一種比較特殊的狀況,固然也有兩個比例不同的,這時就會使得圖形變形扭曲(由於寬高不能等比例縮放),那麼屬性preserveAspectRatio就須要用來強制統一縮放比來保持圖形的寬高比。

preserveAspectRatio

preserveAspectRatio是svg的一個屬性,做用對象是viewBox,值爲兩個用空格分割的值組合而成。

做用:用來聲明viewBox在視窗viewport中如何定位

preserveAspectRatio="xMidYMid meet"

第一個值,表示viewBox如何與viewport對齊:

  • xMin viewport和viewBox左邊對齊
  • xMid viewport和viewBox x軸中心對齊
  • xMax viewport和viewBox右邊對齊
  • YMin viewport和viewBox上邊緣對齊
  • YMid viewport和viewBox y軸中心點對齊
  • YMax viewport和viewBox下邊緣對齊

x,y能夠自由組合

第二個值的含義:

這個參數用來聲明是否強制統一縮放,也就是如何來維持寬高比,若是是,那麼該方法定義的規則會在viewBox的寬高比不等於viewport寬高比的時候生效。這裏我剛看的時候感受理解上不是很容易,下面就列出我對這個知識點的理解方式,若是有錯歡迎你們一塊兒探討。

  • none 在viewBox的寬高比不等於viewport寬高比時,不會保持圖形的寬高比,圖形會扭曲變形
  • meet 默認值,保持圖形的寬高比進行縮放,使viewport包含viewBox

動手寫一個例子,幫助理解

<svg width="400" height="200" viewBox="0,0,40,40" preserveAspectRatio="xMidYMid meet" style="border:1px solid #7798CB">
    <rect x="0" y="0" width="30" height="15" fill="#5CC26F" />
</svg>

效果:

svg-preserveAspectRatio1

從圖中看到rect被放大到150*75,怎麼計算的呢?

viewBox如今是40*40,寬高比爲1,而viewport是400*200寬高比爲2,兩者如今不相等,viewport與viewBox的寬度比爲:wr=400/40=10/1,高度比爲:hr=200/40=5/1,因爲指定的是meet,那麼就要達到viewport包含viewBox的效果,同時保持viewBox的寬高比,這時viewBox該怎麼同時知足這兩個條件呢?

viewBox仍是很聰明的,它會按wrhr中較小的那個值來進行寬高等比例縮放,這樣就既能保持寬高比,還能被viewport包含啦~上例中得viewBox及裏面的矩形rect的寬高就會都按5倍放大。

slice 保持viewbox的寬高比,使viewBox包含viewport

<svg width="400" height="200" viewBox="0,0,40,40" preserveAspectRatio="xMidYMid slice" style="border:1px solid #7798CB">
    <rect x="0" y="0" width="30" height="15" fill="#5CC26F" />
</svg>

效果:

svg-preserveAspectRatio2

如今是slice,那麼就須要達到viewBox包含viewport的效果,這時候聰明的viewBox就會選擇wrhr中值較大的那個進行放大(這裏是由於viewBox比viewport小,因此須要放大來包含viewport,若是viewBox比viewport大,那麼就須要縮小了,依舊乘以比例較大的那個值),也就是放大10倍,此時rect變爲300*150,超出viewport的部分不顯示,有剪切的效果。

圖形分組

  • svg裏使用<g></g>來建立分組
  • <g>中建立的屬性,子元素是能夠繼承的
  • <g>中能夠用transform來定義座標變換,座標變換會在後面作詳細解釋
  • <g>能夠嵌套使用
<svg>
    <g stroke="blue" fill="none" transform="translate(0, 50)">
        <rect x="0" y="0" width="30" height="15" />
        <circle cx="65" cy="75" r="10" />
    </g>
</svg>

這麼一來就能夠經過一個g,來控制包含在裏面的全部圖形的位置,顏色等屬性。控制位移,那麼就須要瞭解svg裏的座標系統了~且聽下面的分析介紹~~很重要的概念

svg的座標系統

svg中的座標系是這樣的:

svg-coordinates1

水平向右是x軸的正方向,豎直向下是y軸的正方向,角度的正方向爲順時針方向

四個比較重要的座標系:用戶座標系,自身座標系,前驅座標系,參考座標系

用戶座標系

svg的座標系,最原始的座標系,其餘幾個座標系都是從用戶座標系展開的。

viewBox就是定義了在用戶座標系的哪一個位置上看svg,以下圖所示

svg-coordinates2

自身座標系

自身座標系是圖形自身,或者分組的座標系

好比

<svg>
    <rect x="0" y="0" width="30" height="15" fill="#5CC26F" />
</svg>

這個矩形自身有一個座標系,rect裏的x,y,width,height等屬性都是根據其自身座標系來定義的。

圖片描述

圖中綠色的座標系就是rect的自身座標系

前驅座標系

前驅座標系就是父容器的座標系,上圖中,rect的前驅座標系就是用戶座標系。

座標變換實際上就是前驅座標系通過一系列變換以後獲得自身座標系的過程。

<svg>
    <rect x="0" y="0" width="30" height="15" transform="translate(50,50)" fill="#5CC26F" />
</svg>

圖片描述

通過transform進行水平和豎直方向的50px的座標偏移以後,rect的自身座標系就跑到了上圖中綠色座標系的位置。若rect的屬性x,y分別有值,好比x="10",y="10",則是相對於自身座標系而言的。

參考座標系

選取一個座標系做爲參考座標系,以此來描述圖形的位置

<svg>
    <rect x="0" y="0" width="30" height="15" transform="translate(50,50)" fill="#5CC26F" />
</svg>

仍是這個例子,若是咱們把用戶座標系做爲參考座標系,那麼在參考座標系下,矩形rect的位置就是(50,50)。

座標變換

svg中的座標變換指的是將一個座標系變換到另外一個座標系的過程描述。

座標變換中起到很大做用的一個屬性,就是上面用到過的transform

transform就是定義了前驅座標系到自身座標系的一個線性變換

語法:

  • translate(<x>,<y>) x表明x軸上的移動的值,y表明y軸上的移動的值。
  • rotate(<deg>) 按角度deg進行旋轉,自身座標系相對於其前驅座標系進行旋轉
  • scale(<sx>,<sy>) sx表明沿x軸的縮放值,用來水平延長或者拉伸元素;sy表明沿y軸縮放值,用來垂直延長或者縮放元素。
  • matrix(<a> <b> <c> <d> <e> <f>) 經過一個有6個值的變換矩陣聲明一個變換。matrix(a,b,c,d,e,f)等同於添加變換matrix[a b c d e f]。較少使用。

注意:若是有連續變換,那麼每次的變換都是基於前一個變換後獲得的自身座標系的基礎上進行變換。

path

路徑path表現的是一個圖形的外邊沿,能夠被填充,能夠做爲筆畫,能夠做爲裁剪路徑,或者任意前面三種的組合。path實際上就是用指令來控制畫筆,將畫筆放到某一個點上,而後拖動畫筆,畫出直線或曲線。

path中的屬性d用來指定路徑位置和形狀,指令以下:

  • M 參數:x y
    功能:將畫筆移動到點(x,y)
  • L 參數:x y
    功能:畫筆從當前的點繪製線段到點(x,y)
  • H 參數:x
    功能:畫筆從當前的點繪製水平線段到點(x,y0)
  • V 參數:y
    功能:畫筆從當前的點繪製豎直線段到點(x0,y)
  • A 參數:rx ry x-axis-rotation large-arc-flag sweep-flag x y
    功能:畫筆從當前的點繪製一段圓弧到點(x,y)
  • C 參數:x1 y1, x2 y2, x y
    功能:畫筆從當前的點繪製一段三次貝塞爾曲線到點(x,y)
  • S 參數:x2 y2, x y
    功能:光滑版本的三次貝塞爾曲線(省略第一個控制點)
    註釋:1.若是上一個曲線也是貝塞爾曲線,那麼在與上一個曲線的交界處,省略的第一個控制點與上一個曲線的第二個控制點關於交界點是鏡像關係;2.若是上一個曲線不是貝塞爾曲線,那麼會把上一個圖形的終點位置做爲貝塞爾曲線的第一個控制點
  • Q 參數:x1 y1, x y
    功能:繪製二次貝塞爾曲線到點(x,y)
  • T 參數:x y
    功能:光滑版本的二次貝塞爾曲線(省略控制點)
    註釋:同S的註釋
  • Z 無參數
    功能:繪製閉合圖形,若是d屬性不指定Z命令,則繪製線段,而不是封閉圖形。

注意:命令區分大小寫,大寫表示座標參數爲絕對位置,小寫爲相對位置(相對於當前畫筆的相對位置);最後的參數表示最後要到達的位置;上個命令結束的位置就是下一個命令開始的位置;命令能夠重複參數表示重複執行同一條命令。

屬性能夠連續使用,舉個例子:

<svg>
    <path d="M100 100 L150 300 L200 300 Z" />
</svg>

svg-path1

首先將畫筆放到(100,100)處,而後移動畫筆到(150,300)畫出直線,而後又畫直線到(200,300),最後在點(100,100)處關閉路徑,造成閉合圖形。

說一下弧線參數含義

A rx ry x-axis-rotation large-arc-flag sweep-flag x y

  • rx,ry 指橢圓的兩個半軸大小
  • x-axis-rotation 指橢圓的x軸與水平方向順時針方向夾角,能夠想像成一個水平的橢圓繞中心點順時針旋轉的角度
  • large-arc-flag 表示是否選擇弧長較長的那段弧線,1表示大角度弧線,0爲小角度弧線
  • sweep-flag 肯定起點至終點的方向,1爲順時針,0爲逆時針
  • x,y 弧的終點座標
<svg width="100%" height="1000px">
        <path d="M 100 100 h 100 l -100 100 v -100 M 200 100 A 100 100 0 0 1 100 200"  fill="#fff" stroke="red"/>
</svg>

svg-path2

關於貝塞爾曲線,能夠參考這裏的demo加深理解,裏面的起點和終點之間的點,就是貝塞爾曲線的控制點。

相關文章
相關標籤/搜索