Day3-认识 SVG

本篇大纲:DOM 元素、SVG 重点概述、SVG 形状/线条/路径/文字、SVG样式

上一章有提过在学习D3之前需要具备的知识,这边就来讲解其中最重要的一点:SVG!由於 D3.js 的画面渲染部分是用 SVG 运作,因此如果完全不懂 SVG 的话,就无法顺利使用 D3 了~现在来说说 SVG 是什麽吧!

先来说说 DOM 元素(Document Object Model)

在讲SVG之前,我们需要先了解 html DOM树 的概念。为什麽得要先了解DOM呢? 主要是因为 D3 是靠着操作 DOM 元素来进行node节点增减,再透过 SVG 去渲染图表

DOM 的全名是 Document Object Model,中文叫做文件物件模型。听起来好像很复杂抽象,但其实就是把 HTML 文件中的每个标签都定义成物件,最後这些物件会形成像是树状的结构。像下图就是一个基本的html文件树状图:
https://ithelp.ithome.com.tw/upload/images/20210915/201349306TPKBBfOQw.jpg

所以如果你的程序码长这样

<div>
    <div class="box">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
    <div class="list">
        <ul>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
</div>

你的 DOM 树结构就会是这样
https://ithelp.ithome.com.tw/upload/images/20210915/201349300R8MfE3cWR.jpg

这里的每一个 html 标签就视为一个 node 节点,D3 是将数据资料绑定到节点,并增减节点来建立图表。

然後呢?快说 SVG!

有了以上的 DOM 概念後,我们就可以来看SVG啦!SVG 的全名是 Scale Vector Graphics (可缩放向量图型),是以** XML 文字档来建立 2D 的向量图形**,因此开发者可以直接在 HTML 档案中使用 SVG,而且也支援动画跟互动的操作。

SVG 图形可以有不同的形式

  • 独立的文件 ⇒ 比较少见
  • 包在 HTML 档案中 ⇒ 最常见,为 < svg > < /svg >元素
  • 当作图片来源引入 ⇒ < img src="smile.svg" >

D3.js使用的就是第二种形式,在 html 档案中使用svg标签,并宣告它的空间范围。接着在这个范围内放入要绘制的图形元素标签,以及它的位置、颜色等等相关资讯

<svg width="500" height="500">
	 这边放入要绘制的图形元素标签...
</svg>

SVG 的重点概述

了解SVG之後,我们来看一下SVG的一些基本概念

  1. SVG 是基於 XML 文字档格式,产生DOM树 (不像canvas是平面画布)

  2. SVG 定义了一系列图形元素,例如「圆或矩形等基本形状、文字、直线、曲线」等等,然後再透过外观属性去改变这些形状的尺寸、位置、颜色等等

    例如:svg 定义的 < rect > 矩形元素,< rect > 透过外观属形 x, y 去控制图形位置;width, height 控制图形大小;style 则控制边框、颜色

<svg width="400" height="200" style="border:1px solid red">
    <rect x="20" y="20" width="300" height="100" 
          style="fill:rgb(255, 0, 255); stroke-width:3; stroke:rgb(0,0,0)" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930wrArcKnDh7.jpg

  1. 除了形状之外,svg 也有许多结构元素,例如: < svg >、 < g >、< use >。大家在看别人的 svg 程序码时,应该蛮常看到下图 这个元素,它就是其中一种 SVG 的结构元素
    https://ithelp.ithome.com.tw/upload/images/20210915/20134930Hd82vIv1Vz.jpg

那你可能就会问,什麽是结构元素呢?结构元素是一种容器元素,不会绘制外型,而是用来包裹多个子元素,这样一来就能将其下的子元素包成一个大包的共同元素,统一去改变位置、形状或颜色等等。

我们可以简单整理一下结构元素的特点:

  • 套用到结构元素上的属性(移动、换色)会同步套用到子项目
  • 没有形状,负责组装复杂图形物件成为共同集合,并可一次移动与操作这个图形集合
  1. 跟一般的 html 撰写一样,SVG 也是按照文件的顺序进行渲染,所以後来写的元素会遮盖掉先前出现的元素
  2. SVG 使用的是图形座标,因此原点是左上角,由上而下、从左至右
  3. SVG 可以接收使用者事件,并回应事件进行互动
  4. SVG 图形原则上是无限大,width / height 只是定义 viewport (可视范围)。
    这点很重要,正因为 svg 图形原则上是无限大,所以如果图案超过 svg 的可视范围,图案一样存在只是我们看不到而已

https://ithelp.ithome.com.tw/upload/images/20210915/20134930RYDACwGEQk.jpg

但是不可能所有数据都刚好符合我们设定的视窗比例,这也正是为什麽、要定义比例尺的原因。透过比例尺去定义出视窗大小跟数据的比例,才能将绘制完的图形完整放到我们的 svg 视窗内。

看完这些之後,相信大家对 SVG 已经有概念了。接下来我们来看看 SVG 定义的一些形状、线条、路径,以及它们的属性吧!

SVG 形状

svg 已经先帮我们定义好一些形状,并赋予相对应的标签。所们只要使用这些标签,并添加固定的属性,就可以画出一些基本的形状啦~这些定义好的形状包含:

  • < rect > 矩形
属性 意义
x, y 左上角座标宽、高
width, height 宽高
rx, ry 水平/垂直边角半径

范例:从坐标轴 x 20 与 y 20 的地方开始,建立一个宽300、高100的长方形;内部填满桃红色,并且要有3px的粗黑边框

<svg width="400" height="200" style="border:1px solid red">
    <rect x="20" y="20" width="300" height="100" 
          style="fill:rgb(255, 0, 255); stroke-width:3; stroke:rgb(0,0,0)" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930kdZi9467wO.jpg

  • < circle > 圆形
属性 意义
cx, cy 水平/垂直中心座标
r 半径

范例:从坐标轴 x 100 与 y 50 的地方开始,建立一个半径为40的圆型,内部填满红色,且要有3px的粗黑边框

<svg width="400" height="150" style="border:1px solid red">
  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930fldzFvNP43.jpg

  • < ellipse > 椭圆形
属性 意义
cx, cy 中心座标水平
rx, ry 垂直半径

范例:从坐标轴 x 200 与 y 80 的地方开始,建立一个x半径为80、y半径为50的椭圆型,内部填满淡粉红色,且要有3px的粗黑边框

<svg width="400" height="150">
  <ellipse cx="200" cy="80" rx="80" ry="50" stroke="black" stroke-width="3" fill="pink"></ellipse>
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930ZuN7cnvUZw.jpg

SVG 线条

  • < line > 线条
属性 意义
x1, x2 座标开始点
y1, y2 座标结束点

范例:绘制第一端在圆点( x0, y0 ),另外一端在( x200, y200 )的直线,粗度为2px

<svg width="400" height="200">
  <line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(0,0,255); stroke-width:2" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930QOLlXcdfFJ.jpg

  • < polyline > 折线
属性 意义
points 表示每个点之间的 X、Y 座标

范例:绘制端点 20,50 40,25 60,40 80,120 120,140 160,180 的折线,粗度为3px

<svg width="400" height="200">
    <polyline
      points="20,50 40,25 60,40 80,120 120,140 160,180 "
      style="fill: none; stroke: orangered; stroke-width: 3"
    />
  </svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930at1lxkGdwZ.jpg

  • < polygon > 多边形
    数值与折线相同,只是 polygon 会产生闭合折线并填满区块
属性 意义
points 表示每个点之间的 X、Y 座标

范例:绘制端点 200,10 250,190 160,180 的闭合形状,颜色填满为绿色,边框粗度为3px

<svg width="400" height="200">
  <polygon
    points="200,10 250,190 160,180"
    style="fill: lime; stroke: purple; stroke-width: 1"
  />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930YB5PzBETQK.jpg

SVG 路径、文字

  • < path > 路径
属性 意义
d 路径

< path > 元素是在 SVG 中最常见的指令,它可以透过命令语言绘制任何形状。它只有一个 d 属性,而属性值是由「空白间隔的命令」+「座标字串」组合而成。

所有的「空白间隔的命令」都是用一个英文字元指令,并具备两种形式

  1. 大写字母:表示跟随在後方的座标是绝对座标
  2. 小写字母:表示跟随在後方的座标是相对座标

习惯上在一开始时,会用 M 命令移动到一个明确的位置再开始绘制。至於座标的部分,在 < path > 中的座标都没有单位,而且可以有负值。

以下列出几个常见的命令英文代号,但由於绘制路径很复杂,一般我们不会自己算座标去画图,而是使用一些辅助工具 (例如 AI illustrator) 画好图片後存成SVG档,而D3.js 也提供了函式去产生相对应的路径。

命令英文代号

  • M, m 移动至特定位置 (不会绘制线条)
  • L, l 画一条直线到...
  • H, h 水平线
  • V, v 垂直线
  • Z, z 把目前座标的点跟第一点连起来,并形成封闭路径
  • C, c 立方贝兹曲线
  • S, s 从多个控制点画立方贝兹曲线
  • Q, q 画贝兹曲线
  • T, t 从多个控制点画贝兹曲线
  • A, a 从目前的位置画椭圆曲线
<svg width="400" height="200">
  <path
    d="M50 20 C80 90,40 200,250,100"
    stroke="black"
    fill="none"
    stroke-width="2"
  />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930GWBJTYOPnG.jpg

也可以透过不同线段画出有趣的图

<svg width="100" height="100">
    <path
      d="M25,15 L25,30
         M75,15 L75,30
         M15,50 C20,80 80,80 85,50"
      stroke="black"
      fill="none"
      stroke-width="2"
    />
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930Tt3H0y3FNT.jpg

  • < text > 文字
属性 意义
x,y 文字的座标
dx 以 x 座标为基准,平行移动文字距离(正为往右,负为往左)。
dy 以 Y 座标为基准,垂直移动文字距离(正为往上,负为往下)。
textLength 设定这段文字的长度,和 lengthAdjust ( 设定对这段文字长度的调整 ) 搭配运作
text-anchor 文字开始绘制位置 (靠左、置中、靠右对齐)
rotate 每个文字的旋转角度,若是要整组文字一起旋转可以使用 transform="rotate()"

特别的是,只要把属形值改为阵列 [ ] ,这些属性就可以针对单一字元设定。

<svg width="400" height="200">
    <text x="50,60,80" y="80,120,40" fill="blue" text-anchor="start">
      SVG 真有趣!
    </text>
</svg>

https://ithelp.ithome.com.tw/upload/images/20210915/20134930jZGE3Y78dL.jpg


SVG的样式、转换属性

看完上述SVG定义的图形後,会发现这些标签还跟着很多属性的设定。有了这些属性,我们才能设定形状的样式、动画等等,以下就来介绍一些常见的属性:

常用表现属性:

常用表现属性 用途
< stroke > 图形的边框颜色
< stroke-width > 图形的边框粗细
< fill > 图形的内部填满颜色
< font-size > 文字尺寸
< opacity > 图形的透明度
< visibility > 图形是否可视

.
转换属性:移动、旋转、延展、推移

常用转换属性 用途
< rotate > 图形旋转
< transform > 图形变形

.

相关补充资源

如果看完这边後,想再更深入了解SVG的话,可以参考 W3C的SVG教学 ,里面根据每个SVG的图形跟样式都有个别说明~

关於SVG的属性,我这边只介绍一些比较常用的~如果想看完整的属性列表,则可以到MDN的页面查找

.

Github Page 图表与 Github 程序码

最後,这边附上本章的程序码与图表 GithubGithub Page,需要的人请自行取用~

今天终於平安的结束啦~明天再见!


<<:  CSS 权重优先级

>>:  【LeetCode】Backtracking

【Day 13】jQuery下载安装

何谓jQuery? 说明:是一套跨浏览器的JavaScript函式库,用於简化HTML与JavaSc...

Rust-定义泛型函式

Rust是强型别语言,执行严格的资料型别检查,因此当定义使用某种型别参数的函式时比如说 square...

连续 30 天 玩玩看 ProtoPie - Day 2

第二天,不废话,继续摸摸摸。 ProtoPie 的 Conceptual model 影片开始解释 ...

qt 自定义控件 不同萤幕

自定义了一个数字键盘: 自己电脑跑起来是正常的,但是切换到一个分辨率不一样的电脑时就跑掉了,不整齐;...

Day 03 Introduction to AI

Challenges and risks with AI Bias can affect resul...