跳至主要内容
工具记录约 13 分钟

SVG 矢量图:从基础代码到实战应用

系统整理 SVG 的坐标系、基础形状、路径、样式、复用、变换、动画和 Web 集成方式。

#SVG#矢量图#Web#图形基础
本文目录
  1. 一、什么是 SVG?
  2. 二、SVG vs 位图(PNG/JPG)
  3. 三、SVG 基本结构
  4. 3.1 最小可用 SVG
  5. 3.2 viewBox —— 理解 SVG 的坐标系
  6. 四、基础形状
  7. 4.1 矩形 rect
  8. 4.2 圆形 circle
  9. 4.3 椭圆 ellipse
  10. 4.4 直线 line
  11. 4.5 折线 polyline
  12. 4.6 多边形 polygon
  13. 五、Path 路径 —— SVG 的核心
  14. 5.1 基本语法
  15. 5.2 画一个三角形
  16. 5.3 画曲线(贝塞尔)
  17. 5.4 画圆弧
  18. 六、样式与美化
  19. 6.1 基础样式属性
  20. 6.2 用 CSS 写样式
  21. 6.3 渐变
  22. 七、文本
  23. 八、分组与复用
  24. 8.1 <g> 分组
  25. 8.2 <defs> + <use> 定义与引用
  26. 8.3 <symbol> 可复用符号
  27. 九、变换(Transform)
  28. 十、高级特性
  29. 10.1 裁剪路径 clipPath
  30. 10.2 遮罩 mask
  31. 10.3 滤镜 filter
  32. 十一、动画
  33. 11.1 CSS 动画(推荐)
  34. 11.2 SMIL 动画(SVG 原生)
  35. 11.3 高亮动画示例(适合教学场景)
  36. 十二、SVG 在 Web 中的使用方式
  37. 12.1 内嵌到 HTML(最灵活)
  38. 12.2 作为图片引用
  39. 12.3 作为背景图
  40. 12.4 用 JavaScript 动态生成
  41. 十三、实战案例:物理题示意图
  42. 十四、速查表
  43. 常用元素
  44. Path 命令速查
  45. 常用样式属性

一、什么是 SVG?

SVG(Scalable Vector Graphics,可缩放矢量图形)是一种用 XML 代码描述图形 的格式。你写的不是像素点,而是一行行类似 HTML 的标签,浏览器读取这些标签后渲染出图形。

核心特点:

  • 矢量:放大缩小不失真,和分辨率无关

  • 代码驱动:纯文本,可读、可编辑、可程序化生成

  • DOM 元素:在 HTML 中直接内嵌,可以被 CSS 和 JavaScript 操作

  • 文件极小:图标类图形通常只有几百字节

一句话理解:SVG 就是用代码画图,而不是用像素拼图


二、SVG vs 位图(PNG/JPG)

对比项SVG(矢量图)PNG / JPG(位图)
本质数学公式描述图形(坐标、路径)像素矩阵,每个像素一个颜色值
放大效果始终清晰,不失真放大后出现马赛克/模糊
文件大小简单图形极小(几百字节)与分辨率正相关,通常更大
可编辑性直接改代码就能修改图形需要图像编辑软件(PS 等)
适用场景图标、Logo、图表、示意图、教学图形照片、复杂渐变纹理
动画原生支持(CSS/SMIL/JS)需要 GIF 或视频格式

三、SVG 基本结构

3.1 最小可用 SVG

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
  <circle cx="100" cy="100" r="50" fill="red" />
</svg>

这段代码做了什么:

  • <svg>:根元素,声明这是一个 SVG 图形

  • xmlns:XML 命名空间,告诉浏览器这是 SVG 标准

  • width / height:画布尺寸

  • <circle>:画一个圆,圆心 (100,100),半径 50,红色填充

3.2 viewBox —— 理解 SVG 的坐标系

viewBox 是 SVG 中最重要的概念之一,它定义了内部坐标系

<svg viewBox="0 0 100 100" width="200" height="200">
  <circle cx="50" cy="50" r="25" fill="blue" />
</svg>

关键理解:

  • viewBox="0 0 100 100":内部坐标从 (0,0) 到 (100,100),定义了一个 100×100 的逻辑画布

  • width="200" height="200":实际渲染成 200×200 像素的物理画布

  • 效果:内部 100×100 的图形被等比放大到 200×200,每个逻辑单位 = 2 像素

类比:viewBox 是「地图的经纬度范围」,width/height 是「打印出来的纸张大小」。同一张地图可以印在 A4 上也可以印在 A0 上,清晰度不变——这就是矢量。

属性作用示例
viewBox定义内部坐标系(x, y, width, height)viewBox="0 0 400 300"
width / height渲染尺寸(像素或百分比)width="100%"
xmlnsXML 命名空间(必须)xmlns="http://www.w3.org/2000/svg"

四、基础形状

SVG 内置了 6 种基本形状,掌握这些就能画 80% 的图形。

4.1 矩形 rect

<rect x="10" y="10" width="80" height="50"
      rx="10" ry="10"
      fill="#4A90D9" stroke="#2C3E50" stroke-width="2" />
属性含义
x, y左上角坐标
width, height宽高
rx, ry圆角半径(类似 CSS 的 border-radius)

4.2 圆形 circle

<circle cx="50" cy="50" r="40" fill="none" stroke="red" stroke-width="3" />
属性含义
cx, cy圆心坐标
r半径

4.3 椭圆 ellipse

<ellipse cx="50" cy="50" rx="40" ry="20" fill="lightgreen" />

rx 和 ry 分别是水平半径和垂直半径,不等就是椭圆。

4.4 直线 line

<line x1="0" y1="0" x2="100" y2="100" stroke="black" stroke-width="2" />

从 (x1,y1) 到 (x2,y2) 画一条线。直线没有 fill,只有 stroke。

4.5 折线 polyline

<polyline points="0,0 50,50 100,0 150,50" fill="none" stroke="blue" />

points 是一组坐标对,用空格分隔。画出的是连续线段,不自动闭合。

4.6 多边形 polygon

<polygon points="50,0 100,100 0,100" fill="yellow" stroke="black" />

和 polyline 类似,但自动闭合(最后一个点和第一个点连起来)。上面这个画了一个三角形。


五、Path 路径 —— SVG 的核心

<path> 是 SVG 中最强大的元素,能画任意形状。所有基础形状都可以用 path 实现,但 path 能做的远不止于此。

5.1 基本语法

<path d="M 10 10 L 90 10 L 90 90 Z" fill="none" stroke="black" />

d 属性是一串「命令 + 参数」的序列,就像给画笔下达指令:

命令含义参数类比
MMove To(移动到)x y抬笔移到这个位置
LLine To(画直线到)x y落笔画直线到这里
HHorizontal Line(水平线)x只改变 x,y 不变
VVertical Line(垂直线)y只改变 y,x 不变
ZClose Path(闭合)回到起点,闭合路径
CCubic Bezier(三次贝塞尔曲线)x1 y1 x2 y2 x y两个控制点 + 终点
QQuadratic Bezier(二次贝塞尔曲线)x1 y1 x y一个控制点 + 终点
AArc(圆弧)rx ry rotation large-arc sweep x y画一段椭圆弧

5.2 画一个三角形

<path d="M 50 10 L 90 90 L 10 90 Z" fill="lightblue" stroke="navy" />

读法:移动到 (50,10) → 画线到 (90,90) → 画线到 (10,90) → 闭合回到起点。

5.3 画曲线(贝塞尔)

<!-- 二次贝塞尔:Q 控制点 终点 -->
<path d="M 0 100 Q 50 0 100 100" fill="none" stroke="red" />

<!-- 三次贝塞尔:C 控制点1 控制点2 终点 -->
<path d="M 0 100 C 30 0 70 0 100 100" fill="none" stroke="blue" />

贝塞尔曲线的直觉:控制点像磁铁,把直线「拉弯」。控制点离线越远,弯曲幅度越大。

5.4 画圆弧

<path d="M 50 50 A 30 30 0 0 1 80 50" fill="none" stroke="green" />

A 命令参数最多,7 个值:

参数含义
rx, ry椭圆的两个半径
rotation椭圆的旋转角度(度)
large-arc-flag0 = 取小弧,1 = 取大弧
sweep-flag0 = 逆时针,1 = 顺时针
x, y终点坐标

圆弧是 SVG 中最复杂的命令,但在画物理图形(斜面、圆弧轨道)时非常有用。


六、样式与美化

6.1 基础样式属性

属性作用示例值
fill填充颜色red / #FF5733 / rgb(255,0,0)
fill-opacity填充透明度0.5(0~1)
stroke描边颜色black / #333
stroke-width描边粗细2(默认 1)
stroke-dasharray虚线模式5,3(画 5 空 3)
stroke-linecap线帽样式butt / round / square
opacity整体透明度0.8

6.2 用 CSS 写样式

<svg viewBox="0 0 100 100">
  <style>
    .box { fill: #4A90D9; stroke: #2C3E50; stroke-width: 2; }
    .highlight { fill: #FF6B6B; opacity: 0.6; }
  </style>
  <rect class="box" x="10" y="10" width="30" height="30" />
  <rect class="highlight" x="10" y="10" width="30" height="30" />
</svg>

SVG 里可以写 <style> 标签,用法和 HTML 的 CSS 一样。这在需要批量控制样式或实现高亮切换时非常实用。

6.3 渐变

线性渐变:

<defs>
  <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0%" stop-color="red" />
    <stop offset="100%" stop-color="blue" />
  </linearGradient>
</defs>
<rect x="0" y="0" width="100" height="50" fill="url(#grad1)" />

径向渐变:

<defs>
  <radialGradient id="grad2">
    <stop offset="0%" stop-color="yellow" />
    <stop offset="100%" stop-color="orange" />
  </radialGradient>
</defs>
<circle cx="50" cy="50" r="40" fill="url(#grad2)" />

关键点:渐变定义在 <defs> 里,用 id 命名,使用时 fill="url(#id)" 引用。


七、文本

除了图形,SVG 也可以用 <text> 元素直接绘制文字,常用于坐标标注和图内说明。

<text x="10" y="50" font-size="20" font-family="Arial" fill="black">
  Hello SVG
</text>
属性含义
x, y文字基线的起始位置(注意:y 是基线位置,不是顶部)
font-size字号
font-family字体
text-anchor对齐方式:start / middle / end
dominant-baseline垂直对齐:hanging / middle / alphabetic

多行文本用 <tspan>

<text x="10" y="20" font-size="14">
  <tspan x="10" dy="0">第一行</tspan>
  <tspan x="10" dy="20">第二行</tspan>
</text>

八、分组与复用

8.1 <g> 分组

<g transform="translate(50, 50)">
  <circle cx="0" cy="0" r="20" fill="red" />
  <rect x="-30" y="-30" width="60" height="60" fill="none" stroke="black" />
</g>

<g> 把多个元素打包成一组,可以统一设置样式、变换、ID。类似于 Photoshop 的「编组」。

8.2 <defs> + <use> 定义与引用

<defs>
  <g id="arrow">
    <line x1="0" y1="0" x2="40" y2="0" stroke="black" stroke-width="2" />
    <polygon points="40,0 35,-3 35,3" fill="black" />
  </g>
</defs>

<!-- 复用箭头,放在不同位置 -->
<use href="#arrow" x="10" y="10" />
<use href="#arrow" x="10" y="50" />
<use href="#arrow" x="10" y="90" />

定义一次,引用多次。<defs> 中的内容不会直接渲染,只有被 <use> 引用时才显示。

8.3 <symbol> 可复用符号

<symbol id="icon-star" viewBox="0 0 24 24">
  <polygon points="12,2 15,9 22,9 17,14 19,21 12,17 5,21 7,14 2,9 9,9" />
</symbol>

<use href="#icon-star" x="0" y="0" width="24" height="24" fill="gold" />
<use href="#icon-star" x="30" y="0" width="48" height="48" fill="red" />

<symbol><g> 类似,但自带 viewBox,适合定义可缩放的图标库。


九、变换(Transform)

变换可以作用在单个元素或 <g> 分组上,改变其位置/角度/大小。

变换语法含义
translatetranslate(x, y)平移
rotaterotate(angle, cx, cy)绕 (cx,cy) 旋转 angle 度
scalescale(sx, sy)缩放
skewX / skewYskewX(angle)倾斜
matrixmatrix(a,b,c,d,e,f)自定义 2D 变换矩阵
<!-- 原始矩形 -->
<rect x="0" y="0" width="40" height="20" fill="blue" />

<!-- 平移 + 旋转 45 度 -->
<rect x="0" y="0" width="40" height="20" fill="red"
      transform="translate(50, 50) rotate(45)" />

<!-- 放大 2 倍 -->
<rect x="0" y="0" width="40" height="20" fill="green"
      transform="translate(100, 50) scale(2)" />

十、高级特性

10.1 裁剪路径 clipPath

<defs>
  <clipPath id="clip1">
    <circle cx="50" cy="50" r="30" />
  </clipPath>
</defs>

<!-- 只显示圆形区域内的矩形 -->
<rect x="0" y="0" width="100" height="100" fill="blue"
      clip-path="url(#clip1)" />

裁剪路径就像蒙版,只显示路径内的部分。在物理图形中可以用来:高亮滑块区域、遮挡不需要显示的部分。

10.2 遮罩 mask

<defs>
  <mask id="mask1">
    <rect x="0" y="0" width="100" height="100" fill="black" />
    <circle cx="50" cy="50" r="30" fill="white" />
  </mask>
</defs>

<rect x="0" y="0" width="100" height="100" fill="blue"
      mask="url(#mask1)" />

mask 和 clipPath 类似,但更灵活:白色 = 完全显示,黑色 = 完全隐藏,灰色 = 半透明。可以实现渐变遮罩效果。

10.3 滤镜 filter

<defs>
  <filter id="blur1">
    <feGaussianBlur stdDeviation="3" />
  </filter>
</defs>

<circle cx="50" cy="50" r="30" fill="red" filter="url(#blur1)" />

滤镜可以实现模糊、阴影、发光等效果。常用滤镜:feGaussianBlur(模糊)、feDropShadow(阴影)、feColorMatrix(颜色矩阵)。


十一、动画

11.1 CSS 动画(推荐)

<svg viewBox="0 0 100 100">
  <style>
    @keyframes spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
    }
    .gear { animation: spin 3s linear infinite; transform-origin: 50px 50px; }
  </style>
  <circle class="gear" cx="50" cy="50" r="20" fill="orange" />
</svg>

11.2 SMIL 动画(SVG 原生)

<circle cx="50" cy="50" r="10" fill="red">
  <animate attributeName="r" values="10;30;10" dur="2s" repeatCount="indefinite" />
</circle>

SMIL 通过 <animate> 标签直接在 SVG 元素内定义动画,不需要 CSS。

11.3 高亮动画示例(适合教学场景)

<rect x="10" y="10" width="30" height="30" fill="#4A90D9">
  <animate attributeName="fill"
           values="#4A90D9;#FF6B6B;#4A90D9"
           dur="1s" repeatCount="indefinite" />
</rect>

这个效果就是:矩形颜色在蓝色和红色之间循环闪烁——可以用来做题目讲解时的「高亮提示」。


十二、SVG 在 Web 中的使用方式

画好的 SVG 最终要放进网页,常见有以下四种方式。

12.1 内嵌到 HTML(最灵活)

<body>
  <svg viewBox="0 0 100 100" width="200" height="200">
    <circle cx="50" cy="50" r="40" fill="steelblue" />
  </svg>
</body>

直接写在 HTML 里,SVG 变成 DOM 的一部分,可以用 CSS 和 JS 操作每一个元素。

12.2 作为图片引用

<img src="diagram.svg" alt="物理示意图" />

简单但无法通过 JS 操作内部元素。

12.3 作为背景图

.bg {
  background-image: url('pattern.svg');
  background-size: cover;
}

12.4 用 JavaScript 动态生成

// 创建一个 SVG 圆形
const svgNS = "http://www.w3.org/2000/svg";
const circle = document.createElementNS(svgNS, "circle");
circle.setAttribute("cx", "50");
circle.setAttribute("cy", "50");
circle.setAttribute("r", "30");
circle.setAttribute("fill", "red");
document.querySelector("svg").appendChild(circle);

// 修改属性实现高亮
circle.setAttribute("fill", "yellow");
circle.setAttribute("stroke", "orange");
circle.setAttribute("stroke-width", "3");

这段代码展示了「用 JS 动态创建和修改 SVG」——这正是你的实习项目中「讲解时实时高亮物理图形元素」的技术基础。


十三、实战案例:物理题示意图

下面用 SVG 画一个「滑块在斜面上滑动」的物理示意图,并演示如何高亮滑块:

<svg viewBox="0 0 300 200" width="100%">
  <style>
    .highlight { fill: #FF6B6B; stroke: #E74C3C; stroke-width: 2; }
    .normal { fill: #BDC3C7; stroke: #7F8C8D; stroke-width: 1; }
  </style>

  <!-- 地面 -->
  <line x1="20" y1="170" x2="280" y2="170" stroke="#333" stroke-width="2" />

  <!-- 斜面(三角形) -->
  <polygon points="50,170 200,170 200,50" fill="#ECF0F1" stroke="#333" stroke-width="2" />

  <!-- 滑块(高亮状态) -->
  <rect id="block" class="highlight" x="155" y="52" width="30" height="20"
        transform="rotate(-33.7, 170, 62)" />

  <!-- 标注文字 -->
  <text x="165" y="45" font-size="12" fill="#E74C3C" text-anchor="middle">滑块</text>
  <text x="125" y="190" font-size="12" fill="#333" text-anchor="middle">斜面</text>
</svg>

效果说明:斜面用 polygon 画三角形,滑块用 rect + rotate 旋转贴合斜面角度,通过 CSS class 切换实现高亮/取消高亮。

用 JS 控制高亮的代码:

// 高亮滑块
document.getElementById("block").setAttribute("class", "highlight");

// 取消高亮
document.getElementById("block").setAttribute("class", "normal");

十四、速查表

最后把前面出现过的元素、Path 命令和样式属性汇总成表,方便随手查阅。

常用元素

元素用途核心属性
rect矩形x y width height rx
circle圆形cx cy r
ellipse椭圆cx cy rx ry
line直线x1 y1 x2 y2
polyline折线points
polygon多边形points
path任意路径d(命令序列)
text文本x y font-size text-anchor
g分组transform
use引用复用href x y
defs定义(不渲染)
linearGradient线性渐变x1 y1 x2 y2
radialGradient径向渐变cx cy r
clipPath裁剪路径
mask遮罩
filter滤镜

Path 命令速查

命令含义示例
M / m移动到M 10 10
L / l直线到L 90 10
H / h水平线H 90
V / v垂直线V 90
Z / z闭合路径Z
C / c三次贝塞尔C 20 0 80 0 100 50
Q / q二次贝塞尔Q 50 0 100 50
A / a圆弧A 30 30 0 0 1 80 50

常用样式属性

属性作用常用值
fill填充色颜色名 / hex / rgb / none
stroke描边色颜色名 / hex / none
stroke-width描边粗细数字
stroke-dasharray虚线5,3
opacity透明度0~1
transform变换translate/rotate/scale

(注:部分内容可能由 AI 生成)