1. 程式人生 > >資料視覺化系列--svg入門基礎(一)

資料視覺化系列--svg入門基礎(一)

一、前言

1、SVG(Scalable Vector Graphics)可伸縮向量圖形

特點:

(1)使用xml格式來定義圖形;

(2)用來定義web上的使用的向量圖;

(3)改變影象尺寸,圖片質量不受損;

(4)所有元素屬性可以使用動畫;

(5)繼承了W3C標準,在html中使用方式,html直接嵌入svg內容,或者直接引入svg檔案。

/* svg標籤,這裡的rect為矩形,在後面的圖形元素中會詳細說明  */
<svg width="200" height="200">
  <rect width="20" height="20" fill="red"></rect>
</svg>

/* 引入字尾名為.svg的檔案 */
<img src="demo.svg" alt="測試svg圖片">

注意:svg為inline水平元素。且需要繪製的所有圖形都應被包含在<svg></svg>標籤內。

 

2、SVG座標系

特點:(1)y軸向下;(2)順時針方向的角度是正值。

注意:元素的所有操作都是相對自身座標系進行的

 

3、顏色RGB和HSL

RGB: 三個分量:紅色、綠色、藍色,每個分量的取值範圍[0, 255],優點是顯示器更容易解析。

HSL: 三個分量:顏色h、飽和度s%、亮度l%,每個分量的取值範圍分別是[0, 359], [0, 100%], [0, 100%],,其中,h=0表示紅色, h=0表示120綠色,h=0表示240 藍色。

基於HSL的配色方案:http://paletton.com/

 

二、特殊元素

1、foreignObject

foreignObject元素通常被用來在svg程式碼中嵌入html節點。注意:該屬性對IE不支援。<foreignObject>元素的作用是可以在其中使用具有其它XML名稱空間的XML元素,換句話說藉助<foreignObject>標籤,我們可以直接在SVG內部嵌入XHTML元素。通常會與標籤一起使用,在使用者瀏覽器不支援時,告知使用者。

舉個例子:

<svg xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="120" height="50">
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>文字測試foreignObject的功能</p>
      </body>
    </foreignObject>
</svg>

可以看到<foreignObject>標籤裡面有一個設定了xmlns="http://www.w3.org/1999/xhtml"名稱空間的<body>標籤,此時<body>標籤及其子標籤都會按照XHTML標準渲染,實現了SVG和XHTML的混合使用。

這種混合特性有什麼作用呢?作用很多,其中之一就是輕鬆實現SVG內的文字自動換行。

1.1文字自動換行

SVG要實現文字換行,往往需要手動阻斷

<svg xmlns="http://www.w3.org/2000/svg">
  <text font-size="12">
    <tspan x="0" y="10">一段需要word wrap</tspan>
    <tspan x="0" y="26">的文字。</tspan>
  </text>
</svg>

需要2<tspan>元素,這一點都不工程。

但是如果使用<foreignObject>元素,則自動換行就是小菜:

<svg xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="120" height="50">
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p style="font-size:12px;margin:0;">一段需要word wrap的文字。</p>
      </body>
    </foreignObject>
</svg>

1.2將頁面上的DOM元素輕鬆變成圖片

SVG <foreignObject>元素還有其他更高階的應用,就是可以將頁面上的DOM元素輕鬆變成圖片。

原理:

1、獲取對應DOM元素的outerHTML程式碼;

2、放在<foreignObject>元素中;

3、圖片方式顯示我們的SVG圖形;

4、上一步的圖片本質還是SVG,我們可以藉助canvas drawImage()方法將圖片放在畫布上,然後使用canvas.toDataURL()方法轉換成pngjpg圖片。

 

三、作用於svg標籤的屬性

1、viewport

表示svg的可見區域的大小:width和height,控制svg的寬度和高度

2、viewBox

定義使用者視野的位置以及大小,即定義用來觀察SVG檢視一個矩形區域,更形象的解釋就是:SVG就像是我們的顯示器螢幕,viewBox就是截圖工具選中的那個框框,最終的呈現就是把框框中的截圖內容再次在顯示器中全屏顯示!

如:viewBox ='20 20 100 100',前兩個引數表示viewBox視野相對svg檢視的x y座標,後兩個引數表示viewBox的大小。

與svg實際大小的關係如下:

如上圖所示,使用者可以看到的部分是藍色的星星,而星星的另一側是看不到的。

viewBox的使用案例:

1、繪製矩形

<svg width="200" height="200" style="border: 2px solid #58a">
  <rect x="30" y="30" width="100" height="100" fill="#fb3" stroke="none"></rect>
</svg>

2、增加視野viewBox viewBox='0 0 100 100',相當於使用者只能看到SVG檢視中viewBox定義的區域,即下圖紅色框內區域:

viewBox="x, y, width, height" // x:左上角橫座標,y:左上角縱座標,width:寬度,height:高度

body>
   <svg width="200" height="200" style="border:2px solid #58a" viewBox='0 0 100 100'>
        <rect x="30" y="30" width="200" height="200" fill="#fb3" stroke="none"></rect>
   </svg>

最終效果圖:

 

3、preserveAspectRatio屬性

這個屬性也是作用於<svg>元素上,且作用物件都是viewBox。

比如:

preserveAspectRatio="xMidYMid meet"

屬性值為空格分隔的兩個值組合而成。第一個值表示:viewBox如何viePort對齊;第二個值表示:如何維持高寬比(可以為空)。

其中,第一個值又分為兩個部分組成。前半部分表示x方向的對齊。後半部分表示y方向對齊。

 值  含義
 xMin  viewport和viewBox左邊對齊
 xMid  viewport和viewBox的x軸中心對齊
 xMax  viewport和vieBox右邊對齊
 YMin  viewport和viewBox上邊緣對齊。注意:Y是大寫
 YMid  viewport和viewBox的y軸中心點對齊。注意:Y是大寫
 YMax viewport和viewBox下邊緣對齊。注意:Y是大寫 

xMaxYMax表示右-下

xMidYMid表示中-中

第二個值屬性值支援

 值  含義
 meet  保持縱橫比縮放viewBox適應viewport,受
 slice  保持縱橫比,同時比例小的方向放大填滿viewport,攻
 none 扭曲縱橫比,充分適應viewport,變態 

1、圖1:紅色區域為不設定preserveaspectRatio時的可視區域;

2、圖2: 採用與x軸左邊對齊、與y軸上邊緣對齊的方式,保持縱橫比縮放;

3、圖3:保持縱橫比的同時,以比例小的方向即x軸等比放大,填充svg區域

4、圖4:preserveaspectRatio="none",變形充分適應svg

 

四、作用於svg內部元素的樣式

svg支援css選擇器給元素新增樣式

/* 定義樣式 */
.rectStyle {
  fill: yellow;
}
<svg width="200" height="200">
  <rect class="rectStyle" width="20" height="20"></rect>
</svg>

也可以直接在元素中設定樣式:

<svg width="200" height="200">
  <rect width="20" height="20" fill="yellow"></rect>
</svg>

或者寫成style

<svg width="200" height="200">
  <rect style="fill: yellow;" width="20" height="20"></rect>
</svg>

常見的樣式說明:

1、填充

(1)fill:定義填充顏色和文字顏色;

(2)fill-opacity:定義填充顏色的透明度;

(3)fill-rule:指定填充規則,符合填充規則才可被填充,取值:[nonzero | evenodd | inherit],預設值為nonzero。 

nonzero: 該規則判斷點任意方向的射線與圖形路徑的相交情況,預設為數值0,射線從左到右時,每穿過一條路徑,數值加1;從右到左時,每穿過一條路徑,數值減1,最後結果若為0,則表示點不在圖形內部,不能填充。

evenodd:該規則判斷點任意方向的射線與圖形路徑的相交情況,相交個數為奇數,則點在圖形內部,可進行填充;反之在外部,不進行填充。

好像比較難理解這個,fill-rule到底是為了解決什麼問題?

我們看上圖,圖中有一個路徑A-B-C-D-E-F-G-H-I,當我們用fill填充它的時候,我們會發現其中有一個重疊的區域S,那麼這個重疊的區域到底填不填充呢?這,就是fill-rule所幹的事。

分析:沿著A-B-C-D-E-F-G-H-I方向走,我們會發現重疊區域S外部為A-B-C-D-A,形成方向為順時針方向。重疊外部區域S的形成方向為逆時針H-I-A,所以重疊區域S不顯示。這個和fill-rule設定無關,這是預設的。

來看一下經典的五角星問題:

相同的,這裡有一個重疊區域S,不過如何才能知道是重疊區域呢?其實很簡單,就是重疊區域的外面還有東西,而它們都還在整個形狀之內。

我們可以發現五角星的重疊區域S的形成方向和外部是一樣的,這種情況下,fill-rule就起作用了,如果是nonzero,區域S是顯示的,如果是evenodd,區域S則不顯示。

 

2、邊框

(1)stroke:邊框顏色;

(2)stroke-width:邊框寬度;

(3)stroke-opacity:邊框透明,取值[0,1];

(4)stroke-linecap:單條線端點樣式,一般應用於直線或者路徑,取值:[ butt | square | round ],分別是對接、方形和圓形

(5)stroke-dasharray:虛線邊框,可以設定每段虛線的長度和間隔,之間使用逗號分隔或者空格分隔,如:

stroke-dasharray="10, 5, 5, 10"

(6)stroke-dashoffset:設定虛線描邊偏移量,使圖案向前移動

 <svg width="200" height="200" viewBox='0 0 300 300'>
    <line x1="20" y1="20" x2="120" y2="20"
        stroke="red" stroke-width="5" stroke-linecap="butt"
        stroke-dasharray="20 5 5 10">
    </line>
    <line x1="20" y1="60" x2="120" y2="60"
        stroke="red" stroke-width="5" stroke-linecap="butt"
        stroke-dasharray="20 5 5 10" stroke-dashoffset="10">
    </line>
   </svg>

虛線的樣式為 20 5 5 10,偏移量為10,根據下圖可發現第二個虛線,整體向前移動了10個單位

(7)sroke-linejoin:兩條線段之間銜接點的樣式,取值:[ miter | round | bevel ],分別是尖角(圖左一)、圓角(圖左二)和斜角(圖左三)

(8)sroke-miterlimit:預設值4,當miterLength / stroke-width < stroke-miterlimit時,stroke-linejoin值會變成換成bevel斜角。如下圖中,stroke-width為15,根據計算公式,miterLength / stroke-width 約等於5.2,即當stroke-miterlimit小於6時,stroke-linejoin值會變成bevel斜角。

3、透明度

opacity:定義整個圖形的透明度

 

4、字型

(1)font-size:字型大小;

(2)font-family:字體系列的名稱;

(3)font-weight:字型粗細;

(4)font-style:字型樣式,斜體和正常;

(5)text-decoration:下劃線樣式;

(6)text-anchor:設定文字的排列屬性,屬性值[start | middle | end | inherit],如:middle表示,將文字定位原點移動至文字中心。

 

5、變換

基礎概念同css。

(1)transform:同css,預設是左上角為旋轉中心,如:transform="rotate(30)";

(2)transform-origin:同css,設定旋轉的操作中心;

(3)rotate:設定文字元素的旋轉角度,正值為順時針旋轉,注意區分rotate和transform中的rotate,如rotate="30"

而transform中的rotate是對整個元素進行旋轉操作。

 <svg width="200" height="200">
    <text x="10" y="10" dx="10" dy="10" textLength="100" rotate="20">示例文字1</text>
   </svg>
   <svg width="200" height="200">
    <text x="10" y="10" dx="10" dy="10" textLength="100" transform="rotate(20)">示例文字2</text>
   </svg>

 

五、參考

1、http://www.runoob.http://www.runoob.com/svg/svg-tutorial.html

2、http://qiutianaimeili.com/html/page/2018/04/08sh1vbv35yr.