SVG(Scalable Vector Graphics,可缩放矢量图形)是W3C制定的一种基于XML的二维图形描述标准。与JPG、PNG这类由像素点阵组成的位图不同,SVG记录的是图形的几何信息——线条从哪里开始、曲线如何弯曲、区域用什么颜色填充。正因为它保存的是绘图指令而不是像素数据,所以无论放大多少倍都不会模糊,而且文件本质上是纯文本,可以直接用记事本打开编辑,也能被搜索引擎和读屏软件解析。本文将从底层结构入手,讲清楚SVG是如何用XML标签体系来描述二维图形的。

SVG的基本XML结构:文档即图形
一个最小的SVG文件长这样:根元素是<svg>,带有xmlns命名空间声明、宽度高度以及viewBox属性。这段XML本身就是一张合法的图片,把扩展名保存为.svg就能被浏览器直接渲染。
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 100 100"> <circle cx="50" cy="50" r="40" fill="tomato"/> <rect x="20" y="20" width="60" height="60" fill="none" stroke="#333"/> </svg>
根元素上的xmlns="http://www.w3.org/2000/svg"是XML命名空间,它告诉解析器这些标签属于SVG规范而不是HTML。viewBox="0 0 100 100"定义了一个虚拟坐标系:前两个数是坐标系原点,后两个数是坐标系的宽高。浏览器会把这个100x100的坐标系拉伸到width和height指定的实际尺寸上,这个过程是等比映射的,所以坐标系内部的图形会跟着整体缩放,这就是SVG“矢量”特性的直接来源——分辨率无关。
理解viewBox是掌握SVG的关键一步。假设你把viewBox改成0 0 200 100,而实际宽度高度仍是200x200,图形就会被水平方向压缩一倍,因为200个单位被塞进了200像素,而垂直方向100个单位也被拉伸到200像素,图形会变形。很多初学者遇到“SVG图标显示不全”或“图形比例不对”的问题,根源都是viewBox和实际尺寸不匹配。
常用绘图标签与path路径指令
SVG提供了一组语义化的基本形状标签:<circle>画圆、<rect>画矩形、<line>画直线、<ellipse>画椭圆、<polygon>画多边形。这些标签覆盖了大部分简单图形的绘制需求,属性直观易读,比如cx和cy表示圆心坐标,r表示半径。
真正强大的是<path>元素,它通过d属性里的一串指令来描述任意轮廓。指令由单个字母加参数组成:大写M表示绝对坐标移动到某点,小写m表示相对移动;L画直线;C画三次贝塞尔曲线;A画圆弧;Z闭合路径。比如d="M10 10 L90 10 L50 90 Z"描述的是一个三角形:移动到(10,10),画线到(90,10),再画线到(50,90),最后Z回到起点闭合。所有复杂的图标和字体,本质上都是这些指令的组合。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path d="M10 80 C 30 20, 70 20, 90 80"
fill="none" stroke="steelblue" stroke-width="4"/>
<path d="M20 50 Q 60 5 80 50" fill="none" stroke="orange"/>
</svg>上面第一个path用C指令画了一条三次贝塞尔曲线,需要两个控制点和一个终点;第二个path用Q指令画二次贝塞尔曲线,只需一个控制点,形状更平缓。曲线能力是SVG区别于简单绘图API的核心,配合嵌套的<g>分组标签,可以把多个图形组织在一起统一设置样式和变换,例如<g transform="rotate(45)">会让组内所有图形旋转45度。
SVG与位图的差异及典型应用场景
位图存储的是每一个像素的颜色值,放大时像素被强行拉伸就会出现锯齿和模糊;SVG存储的是几何描述,浏览器在渲染时根据当前尺寸实时计算像素,因此任何分辨率下都保持锐利。这一特性让SVG天然适合图标、logo、图表这类需要在不同设备上展示的图形。此外,SVG文件通常比同等视觉效果的位图小得多,尤其是单色图标,几百字节的SVG就能搞定PNG需要几KB才能表达的内容。
SVG的应用远不止静态图形。它是DOM的一部分,每个图形元素都可以用JavaScript和CSS操作,例如给<circle>绑定click事件、通过CSS的:hover改变填充色。SVG还内置了SMIL动画标签,如<animate>可以让属性随时间变化:
<circle cx="50" cy="50" r="20" fill="crimson"> <animate attributeName="r" values="20;35;20" dur="2s" repeatCount="indefinite"/> </circle>
这段代码让圆的半径在20到35之间往复变化,形成呼吸灯效果,不需要任何JavaScript。在HTML中使用SVG有三种方式:直接内联到HTML文档中(可交互性最强)、通过<img>标签引入(最简单但无法用CSS控制内部样式)、或用CSS的background-image作为背景。如果需要在页面里动态操作图形,推荐内联;如果只是展示,img方式更干净。掌握这些基础之后,无论是手写简单图标还是用设计工具导出SVG后再手动优化代码,你都会清楚每一段XML到底在描述什么,这也正是理解SVG的价值所在。