画布可以看成是一个大大的二维平面(甚至可以是无限大的),以
一次绘制,自适应多种容器大小
我们知道想要让图形完全显示,就必须让图形每一点的坐标都处在可见区域内。
但是,我们更常见的需求是,绘制好一个图标后,在多个地方使用,A页面、B页面、C页面...
每次使用图标的尺寸可能都不同,也就是

viewBox属性有四个值:
viewBox="x, y, width, height"
// x:左上角横坐标,y:左上角纵坐标,width:宽度,height:高度
设置了viewBox属性的

这时,画布中x方向0~10, y方向0~10这个区域中不是可见区域,其中的图形就不会显示。
不过为了方便,viewBox属性的左上角坐标(x、y)通常设置为(0,0)。
preserveAspectRatio
除上面的等比缩放之外,另一种常见的情形是viewBox属性的width, height的比例,与

默认情况下,当viewBox属性的width/height,与
它的值为空格分隔的两个值组合而成。第1个值表示,viewBox如何与

再来看第一个值:xMidYMid。它定义viewBox区域相对

svg组件封装
我们上面使用图标都是复制粘贴svg绘制代码,这是低效的,并且不优雅。接下来我们把图标进行组件封装,以便一次定义,多处引用。所幸,svg有一系列内置标签支持组件化。

我们用line标签绘制了一条直线,如果我们想在其他地方绘制相同的直线,就可以为line标签指定一个id。而在需要使用的地方,通过标签设置href属性为之前定义的id即可。
是svg的内置标签,它能获取href属性指向的目标节点,并在别的地方复制它们。
它的效果等同于这些节点被深克隆到一个不可见的DOM中,然后将其粘贴到use标签的位置,很像HTML5中的克隆模板元素。
一个图标的绘制往往需要不止一个标签。这时怎么指定id呢?
我们可以将所有标签放到一个group中,然后给这个group加id。
绘制多种颜色的播放图标,代码就可以简化成下面这样:

第一个黑色按钮主要作用是定义组件,我们并不希望它页面中出现。我们可以修改它的css属性使其隐藏,但更推荐使用标签。
svg 允许我们定义以后需要重复使用的图形元素。 建议把所有需要再次使用的引用元素定义在标签里面。这样做可以增加 svg 内容的易读性和可访问性。 在标签中定义的图形元素不会直接呈现。 你可以在你的视口的任意地方利用 标签呈现这些元素。

中的图标不显示了,但svg还在。我们可以修改svg的css属性使其隐藏,或者尺寸置为0。
为了使图标自适应容器大小,我们使用viewBox属性。
第一直觉是在定义组件的svg标签上使用viewBox属性,但它不起作用。

能获取href属性指向的目标节点,并在别的地方复制它们。它并没有复制定义组件外层的svg标签。
这种情况下,就要用到symbol了。
symbol元素用来定义一个图形模板对象,它可以用一个use元素实例化。symbol元素对图形的作用是在同一文档中多次使用,添加结构和语义。结构丰富的文档可以更生动地呈现出来,类似讲演稿或盲文,从而提升了可访问性。注意,一个symbol元素本身是不呈现的(类似defs)。只有symbol元素的实例(亦即,一个引用了symbol的use元素)才能呈现。
最重要的是,在标签上,可以定义viewBox和preserveAspectRatio两个属性,完美解决了图标组件自适应的问题。

总结
本文主要讲了svg的使用、基础图标绘制、图标尺寸和颜色自适应原理、以及图标组件的封装,以便在项目中更优雅的使用svg。对于复杂的图标,可以在iconfont上下载图标svg代码,再改造成契合自己项目的svg组件。