# SVG

SVG 即可缩放矢量图形

SVG元素:圆形, 矩形, 曲线

一个简单的SVG文档由<svg>根元素和基本的形状元素构成。另外还有一个g元素,它用来把若干个基本形状编成一个组

绘制SVG要注意几点:

  • SVG是一种XML语言, SVG的元素和属性必须按标准格式书写,因为XML是区分大小写的(这一点和html不同)

  • XML语言里的属性值必须用引号引起来,就算是数值也必须这样做

  • SVG的渲染顺序是“后来居上”,越后面的元素越可见

  • g 包含的子元素如果使用 transform (无论是属性还是style设置的),g 的大小将被受影响

  • SVG的使用方式

    • 如果HTML是XHTML并且声明类型为application/xhtml+xml,可以直接把SVG嵌入到XML源码中

    • 如果HTML是HTML5并且浏览器支持HTML5,同样可以直接嵌入SVG。然而为了符合HTML5标准,可能需要做一些语法调整

    • 可以通过 object 元素引用SVG文件:<object data="image.svg" type="image/svg+xml" />

    • 类似的也可以使用 iframe 元素引用SVG文件:<iframe src="image.svg"></iframe>

    • 理论上同样可以使用 img 元素,但是在低于4.0版本的Firefox 中不起作用

    • 最后SVG可以通过JavaScript动态创建并注入到HTML DOM中。 这样具有一个优点,可以对浏览器使用替代技术,在不能解析SVG的情况下,可以替换创建的内容。

简单例子:

// demo.svg
<svg version="1.1"
     baseProfile="full"
     width="300" height="200"
     xmlns="http://www.w3.org/2000/svg">

  <rect width="100%" height="100%" fill="red" />

  <circle cx="150" cy="100" r="80" fill="green" />

  <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>

</svg>

# SVG 元素

# react-矩形

<rect x="60" y="10" rx="10" ry="10" width="30" height="30"/>

  • x: 矩形左上角的x位置

  • y: 矩形左上角的y位置

  • width: 矩形的宽度

  • height: 矩形的高度

  • rx: 圆角的x方位的半径

  • ry: 圆角的i方位的半径

# circle-圆形

<circle cx="25" cy="75" r="20"/>

  • r: 圆的半径

  • cx: 圆心的x位置

  • cy: 圆心的y位置

# Ellipse-椭圆

Ellipse 给制椭圆

<ellipse cx="75" cy="75" rx="20" ry="5"/>

  • rx: 椭圆的x半径

  • ry: 椭圆的y半径

  • cx: 椭圆中心的x位置

  • cy: 椭圆中心的y位置

# line-线条

Line 绘制直线。它取两个点的位置作为属性,指定这条线的起点和终点位置。

<line x1="10" x2="50" y1="110" y2="150"/>

  • x1: 起点的x位置

  • y1: 起点的y位置

  • x2: 终点的x位置

  • y2: 终点的y位置

# polyline-折线

Polyline是一组连接在一起的直线。因为它可以有很多的点,折线的的所有点位置都放在一个points属性中:

<polyline points="60 110, 65 120, 70 115, 75 130, 80 125, 85 140, 90 135, 95 150, 100 145"/>

  • points:点集数列。每个数字用空白、逗号、终止命令符或者换行符分隔开。每个点必须包含2个数字,一个是x坐标,一个是y坐标。 所以点列表 (0,0), (1,1)(2,2)可以写成这样:“0 0, 1 1, 2 2”

# polygon-多边形

polygon和折线很像,它们都是由连接一组点集的直线构成。不同的是,polygon的路径在最后一个点处自动回到第一个点。需要注意的是,矩形也是一种多边形,如果需要更多灵活性的话,你也可以用多边形创建一个矩形

<polygon points="50 160, 55 180, 70 180, 60 190, 65 205, 50 195, 35 205, 40 190, 30 180, 45 180"/>

  • points:

# path-路径

你可以用path元素绘制矩形(直角矩形或者圆角矩形)、圆形、椭圆、折线形、多边形,以及一些其他的形状,例如贝塞尔曲线、2次曲线等曲线。 因为path很强大也很复杂,所以会在下一章进行详细介绍。这里只介绍一个定义路径形状的属性

  • d: 是一个命令+参数的序列, 描述于如何绘制路径的信息,以下是在d中使用的命令:

    • M x y:表示的是“Move to”命令,当解析器读到这个命令时,它就知道你是打算移动到某个点,跟在命令字母后面的,是你需要移动到的那个点的x和y轴坐标 比如移动到(10,10)这个点的命令,应该写成M 10 10

    • L x y: L命令将会在当前位置和新位置(L前面画笔所在的点)之间画一条线段 <path d="M10 10 L90 90" stroke="black"/>

    • H x: 绘制水平线,只需一个参数

    • V y: 绘制垂直线,只需一个参数

    • Z: 闭合路径命令,Z命令会从当前点画一条直线到路径的起点, Z命令不用区分大小写

    <path d="M 10 10 L 90 90 H 50 L 10 10" stroke="black" fill="transparent"/>等同于:<path d="M 10 10 L 90 90 H 50 Z" stroke="black" fill="transparent"/>

    • C: 贝塞尔曲线,C x1 y1, x2 y2, x y (or c dx1 dy1, dx2 dy2, dx dy)

      • 最后一个坐标(x,y)表示的是曲线的终点,(x1,y1)是起点的控制点,(x2,y2)是终点的控制点
    • S:

每一个命令都有两种表示方式,一种是用大写字母,表示采用绝对定位。另一种是用小写字母,表示采用相对定位, 除了Z

  • ``

# SVG属性

  • fill:内容填充

  • stroke: 线条的颜色

  • fill-opacity:控制填充色的不透明度

  • stroke-opacity: 控制描边的不透明度

# svg和canvas区别

  • 从图像类别区分,Canvas是基于像素的位图,而SVG却是基于矢量图形

  • 从结构上说,Canvas没有图层的概念,所有的修改整个画布都要重新渲染,而SVG则可以对单独的标签进行修改

  • 从操作对象上说,Canvas是基于HTML canvas标签,通过宿主提供的Javascript API对整个画布进行操作的,而SVG则是基于XML元素的。

  • 从渲染模式上来说,Canvas属于 即时模式,而SVG则是 保留模式 ,这两种模式的区别可以参见 cshao 的博文: http://www.lifelaf.com/blog/?p=354

  • 从搜索引擎角度分析,由于svg是有大量标签组成,所以可以通过给标签添加属性,便于爬虫搜索

# 适用场景

Canvas 提供的绘图能力更底层,适合做到像素级的图形处理,能动态渲染和绘制大数据量的图形。而 SVG 抽象层次更高,声明描述式的接口功能更丰富,内置了大量的图形、滤镜和动画等,方便进行文档元素的维护,也能导出为文件脱离浏览器环境使用

# 性能差异

之前网上有不少 Canvas 和 SVG 性能对比的文章,得出的结论大体是“Canvas 性能更好,适合更大量数据的渲染”。 其实这么说是有失偏颇的。性能对比要看场景。从底层来看,Canvas 的性能受画布尺寸影响更大,而 SVG 的性能受图形元素个数影响更大

# 定制和交互

比较流行的看法是 SVG 做定制和交互更有优势,因为有类似 DOM 的结构,能快速应用浏览器底层的鼠标事件、CSS 样式、CSS3 动画等。不过基于 Canvas 做上层封装后也能实现类似的定制和交互,并且自由度更高

# 小结

如果单就图表库的视角来看,选择 Canvas 和 SVG 各有千秋。小画布、大数据量的场景适合用 Canvas,譬如热力图、大数据量的散点图等。 如果画布非常大,有缩放、平移等高频的交互,或者移动端对内存占用量非常敏感等场景,可以使用 SVG 的方案。