SVG 基本图形详解
rect、circle、ellipse、line、polyline、polygon 六大基本图形属性与用法。
前置知识:建议先读《SVG 坐标系统与 viewBox》(003-SVGCoordinateSystemViewBox)理解 viewBox 与用户坐标系——本文所有坐标都落在该坐标系上。
学习目标:掌握 rect、circle、ellipse、line、polyline、polygon 六种基本图形的定位方式与必需属性;理解描边的几何行为(居中扩展、端点、拐角、虚线);能避开 polyline 默认填充这类典型陷阱。
1. 矩形 rect
<rect> 绘制矩形,支持圆角。
<svg viewBox="0 0 300 150">
<rect x="10" y="10" width="80" height="60" fill="#4f5bd5" />
<rect x="110" y="10" width="80" height="60" rx="12" ry="12" fill="#00b894" />
<rect x="210" y="10" width="80" height="60" rx="30" ry="10" fill="#d63031" />
</svg>
1.1 属性
| 属性 | 说明 | 默认值 |
|---|---|---|
x / y | 左上角坐标 | 0 |
width / height | 宽高(必需) | - |
rx / ry | 水平/垂直圆角半径 | 0 |
fill | 填充色 | black |
stroke | 描边色 | none |
stroke-width | 描边宽度 | 1 |
当只设置
rx时,ry默认等于rx,形成等圆角。
1.2 圆角矩形技巧
<!-- 仅上方圆角(用 path 实现) -->
<path d="M 10 30 Q 10 10 30 10 L 70 10 Q 90 10 90 30 L 90 70 L 10 70 Z" fill="#4f5bd5" />
<rect> 原生不支持单侧圆角,需用 <path> 配合贝塞尔曲线实现。
2. 圆形 circle
<circle> 由圆心与半径定义。
<svg viewBox="0 0 200 100">
<circle cx="50" cy="50" r="40" fill="#4f5bd5" />
<circle cx="150" cy="50" r="40" fill="none" stroke="#d63031" stroke-width="3" />
</svg>
2.1 属性
| 属性 | 说明 |
|---|---|
cx / cy | 圆心坐标 |
r | 半径(必需) |
fill / stroke | 填充与描边 |
2.2 描边居中特性
SVG 描边以路径为中心,向两侧各扩展 stroke-width/2。这意味着半径 40、描边 4 的圆,实际占据 84×84 区域。
<circle cx="50" cy="50" r="40" stroke="#000" stroke-width="4" fill="none" />
<!-- 实际边界:cx-r-strokeWidth/2 到 cx+r+strokeWidth/2,即 8 到 92 -->
3. 椭圆 ellipse
<ellipse> 用两个半径定义。
<svg viewBox="0 0 200 100">
<ellipse cx="100" cy="50" rx="80" ry="30" fill="#4f5bd5" />
</svg>
3.1 属性
| 属性 | 说明 |
|---|---|
cx / cy | 圆心 |
rx / ry | 水平/垂直半径 |
当
rx === ry时,椭圆等价于圆形。
4. 直线 line
<line> 由两个端点定义。
<svg viewBox="0 0 200 100">
<line x1="10" y1="10" x2="190" y2="90" stroke="#333" stroke-width="2" />
<line x1="10" y1="50" x2="190" y2="50" stroke="#d63031" stroke-width="4" stroke-dasharray="8 4" />
</svg>
4.1 属性
| 属性 | 说明 |
|---|---|
x1 / y1 | 起点 |
x2 / y2 | 终点 |
stroke | 描边色(必需,否则不可见) |
stroke-width | 描边宽度 |
stroke-linecap | 端点形状:butt / round / square |
stroke-dasharray | 虚线模式 |
<line>默认无 fill,必须设置 stroke 才可见。
5. 折线 polyline
<polyline> 由一系列点连接,不闭合。
<svg viewBox="0 0 200 100">
<polyline
points="10,90 50,10 90,90 130,10 170,90"
fill="none"
stroke="#4f5bd5"
stroke-width="2"
/>
</svg>
5.1 points 语法
points="x1,y1 x2,y2 x3,y3 ..."
也可用空格分隔:
points="10 90 50 10 90 90 130 10 170 90"
5.2 fill 陷阱
<!-- 错误:默认 fill=black,会填充封闭区域 -->
<polyline points="10,90 50,10 90,90" />
<!-- 正确:折线需显式设置 fill="none" -->
<polyline points="10,90 50,10 90,90" fill="none" stroke="#000" />
6. 多边形 polygon
<polygon> 类似 polyline,但自动闭合首尾。
<svg viewBox="0 0 200 100">
<polygon points="100,10 190,90 10,90" fill="#4f5bd5" />
<polygon points="100,10 140,50 100,90 60,50" fill="#00b894" stroke="#fff" stroke-width="2" />
</svg>
6.1 常见多边形
| 形状 | points 示例(以中心为参考) |
|---|---|
| 三角形 | 100,10 190,90 10,90 |
| 菱形 | 100,10 140,50 100,90 60,50 |
| 五角星 | 100,10 120,70 180,70 130,105 150,165 100,130 50,165 70,105 20,70 80,70 |
| 六边形 | 100,10 170,50 170,110 100,150 30,110 30,50 |
注意:五角星、六边形的坐标按 200×160 以上画布设计,放进 200×100 视口会被裁剪;使用前先核对 viewBox。
7. 描边属性详解
7.1 stroke-linecap 端点
<line x1="10" y1="20" x2="100" y2="20" stroke="#000" stroke-width="10" stroke-linecap="butt" />
<line x1="10" y1="40" x2="100" y2="40" stroke="#000" stroke-width="10" stroke-linecap="round" />
<line x1="10" y1="60" x2="100" y2="60" stroke="#000" stroke-width="10" stroke-linecap="square" />
| 值 | 效果 |
|---|---|
butt | 平直端点(默认) |
round | 半圆端点 |
square | 方形延伸(多出 stroke-width/2) |
7.2 stroke-linejoin 拐角
<polyline
points="10,90 50,10 90,90"
stroke="#000"
stroke-width="10"
fill="none"
stroke-linejoin="miter"
/>
<polyline
points="110,90 150,10 190,90"
stroke="#000"
stroke-width="10"
fill="none"
stroke-linejoin="round"
/>
<polyline
points="10,140 50,60 90,140"
stroke="#000"
stroke-width="10"
fill="none"
stroke-linejoin="bevel"
/>
| 值 | 效果 |
|---|---|
miter | 尖角(默认,可用 stroke-miterlimit 限制) |
round | 圆角 |
bevel | 斜切 |
7.3 stroke-dasharray 虚线
<!-- 实线 -->
<line x1="10" y1="10" x2="190" y2="10" stroke="#000" />
<!-- 等长虚线:8px 实线 + 4px 空白 -->
<line x1="10" y1="30" x2="190" y2="30" stroke="#000" stroke-dasharray="8 4" />
<!-- 点线:1px 实线 + 4px 空白 -->
<line x1="10" y1="50" x2="190" y2="50" stroke="#000" stroke-dasharray="1 4" />
<!-- 复合虚线:10px + 4px + 2px + 4px -->
<line x1="10" y1="70" x2="190" y2="70" stroke="#000" stroke-dasharray="10 4 2 4" />
7.4 stroke-dashoffset 起始偏移
stroke-dashoffset 控制虚线起始位置,常用于动画绘制线条。
<line x1="10" y1="90" x2="190" y2="90" stroke="#000" stroke-dasharray="180" stroke-dashoffset="0" />
<!-- dashoffset 从 180 → 0 动画可模拟"绘制"效果 -->
8. 基本图形对比
| 元素 | 必需属性 | 是否闭合 | 是否可填充 |
|---|---|---|---|
<rect> | width, height | 是 | 是 |
<circle> | r | 是 | 是 |
<ellipse> | rx, ry | 是 | 是 |
<line> | x1,y1,x2,y2 | 否 | 否(无 fill) |
<polyline> | points | 否 | 是(但通常 fill=none) |
<polygon> | points | 是 | 是 |
9. 综合示例:简洁仪表盘
<svg viewBox="0 0 200 200" width="200" height="200">
<!-- 背景圆 -->
<circle cx="100" cy="100" r="90" fill="none" stroke="#e0e0e0" stroke-width="12" />
<!-- 进度弧(70%) -->
<circle
cx="100"
cy="100"
r="90"
fill="none"
stroke="#4f5bd5"
stroke-width="12"
stroke-dasharray="396 170"
transform="rotate(-90 100 100)"
stroke-linecap="round"
/>
<!-- 中心文本 -->
<text x="100" y="105" text-anchor="middle" font-size="36" fill="#333">70%</text>
</svg>
原理:
- 圆周长 ≈ 2π × 90 ≈ 565.5
- 70% 弧长 ≈ 396,剩余空隙 ≈ 170(只要不小于剩余周长即可)
dasharray "396 170":沿路径先画 396 再空 170,进度从 12 点钟方向顺时针推进rotate(-90 100 100):把默认起点(3 点钟方向)转到 12 点钟方向stroke-linecap="round":端点圆滑
正的 stroke-dashoffset 会让实线段从末端”缩回”,这是后续动画篇里”线条绘制动画”的原理;本例不需要偏移。
小结
初学者要点:
- 六种图形的描述思路分两类:rect / circle / ellipse 是”定位 + 尺寸”,line / polyline / polygon 是”一串端点坐标”。
<line>没有内部区域,不设stroke就完全不可见;<polyline>不闭合却会按 fill 规则填充,几乎总应显式写fill="none"。- 描边以路径为中心向两侧各扩展
stroke-width/2,做精确布局时要预留这半个线宽。
进阶注意:
- SVG 2 把
x/y/width/height/cx/cy/r/rx/ry定义为 CSS 几何属性(geometry properties):内联 SVG 中可以直接写rect { x: 10px; width: 80px; },现代浏览器均支持;d属性的 CSS 化目前只有 Chromium 实现,跨浏览器代码仍应以属性写法为准。 rx/ry超过对应边长一半时,SVG 2 规定自动钳制到一半(如 200 宽的矩形rx="200"等效rx="100"),不会报错。- 进度环本质是
dasharray/dashoffset操作路径长度;给<circle>加pathLength="100"后可直接写dasharray="70 100"表示 70%,免去周长换算(现代浏览器均支持基本图形上的pathLength)。