SVG 基本图形
SVG(Scalable Vector Graphics)使用 XML 标记语言描述矢量图形,支持矩形、圆形、椭圆、线条、折线和多边形等基本图形元素。每个图形都可以通过丰富的属性进行样式控制,包括填充、描边、透明度等。本节将详细介绍 SVG 基本图形的使用方法。
前置知识
阅读本节前,建议先了解:Canvas 性能优化
基础概念
SVG 图形元素是声明式的——你描述要绘制什么图形,浏览器负责渲染。与 Canvas 不同,SVG 元素可以直接被 CSS 样式化,可以用 JavaScript 交互,且天然支持无损缩放。
SVG 基本图形元素一览
| 元素 | 说明 | 常用属性 |
|---|---|---|
<rect> | 矩形 | x, y, width, height, rx, ry |
<circle> | 圆形 | cx, cy, r |
<ellipse> | 椭圆 | cx, cy, rx, ry |
<line> | 直线 | x1, y1, x2, y2 |
<polyline> | 折线 | points |
<polygon> | 多边形 | points |
语法
SVG 根元素
html
<svg width="400" height="300" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
<!-- 图形内容 -->
</svg>viewBox 属性
viewBox 定义了 SVG 的坐标系统和可视区域:
html
<!-- viewBox="minX minY width height" -->
<svg width="200" height="200" viewBox="0 0 100 100">
<!-- SVG 逻辑空间是 100x100,但渲染为 200x200 -->
<circle cx="50" cy="50" r="40" fill="#4285f4"/>
</svg>详细说明
rect - 矩形
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SVG 矩形</title>
<style>
svg { border: 1px solid #ccc; display: block; margin: 10px 0; }
</style>
</head>
<body>
<h1>SVG rect 矩形</h1>
<svg width="500" height="300" viewBox="0 0 500 300">
<!-- 基本矩形 -->
<rect x="20" y="20" width="120" height="80" fill="#4285f4"/>
<!-- 带圆角的矩形 -->
<rect x="170" y="20" width="120" height="80"
rx="10" ry="10" fill="#34a853"/>
<!-- 只描边的矩形 -->
<rect x="320" y="20" width="120" height="80"
fill="none" stroke="#ea4335" stroke-width="3"/>
<!-- 半透明矩形 -->
<rect x="20" y="140" width="120" height="80"
fill="rgba(66, 133, 244, 0.5)" stroke="#4285f4" stroke-width="2"/>
<!-- 透明度矩形 -->
<rect x="170" y="140" width="120" height="80"
fill="#9c27b0" opacity="0.3" stroke="#9c27b0" stroke-width="2"/>
<!-- 大圆角矩形 -->
<rect x="320" y="140" width="120" height="80"
rx="40" ry="40" fill="#ff5722"/>
</svg>
</body>
</html>rect 属性
| 属性 | 说明 | 默认值 |
|---|---|---|
x | 左上角 X 坐标 | 0 |
y | 左上角 Y 坐标 | 0 |
width | 宽度 | 必填 |
height | 高度 | 必填 |
rx | X 方向圆角半径 | 0 |
ry | Y 方向圆角半径 | 0 |
circle - 圆形
html
<svg width="400" height="200" viewBox="0 0 400 200">
<!-- 实心圆 -->
<circle cx="60" cy="80" r="50" fill="#4285f4"/>
<!-- 描边圆 -->
<circle cx="200" cy="80" r="50"
fill="none" stroke="#34a853" stroke-width="3"/>
<!-- 渐变圆 -->
<defs>
<radialGradient id="circleGrad" cx="40%" cy="40%">
<stop offset="0%" stop-color="#ffffff"/>
<stop offset="100%" stop-color="#ea4335"/>
</radialGradient>
</defs>
<circle cx="340" cy="80" r="50" fill="url(#circleGrad)"/>
</svg>circle 属性
| 属性 | 说明 | 默认值 |
|---|---|---|
cx | 圆心 X 坐标 | 0 |
cy | 圆心 Y 坐标 | 0 |
r | 半径 | 必填 |
ellipse - 椭圆
html
<svg width="400" height="200" viewBox="0 0 400 200">
<!-- 水平椭圆 -->
<ellipse cx="100" cy="100" rx="80" ry="40" fill="#4285f4"/>
<!-- 垂直椭圆 -->
<ellipse cx="250" cy="100" rx="40" ry="70" fill="#34a853"/>
<!-- 描边椭圆 -->
<ellipse cx="370" cy="100" rx="25" ry="25"
fill="none" stroke="#ea4335" stroke-width="3"/>
</svg>ellipse 属性
| 属性 | 说明 | 默认值 |
|---|---|---|
cx | 中心 X 坐标 | 0 |
cy | 中心 Y 坐标 | 0 |
rx | X 轴半径 | 必填 |
ry | Y 轴半径 | 必填 |
line - 直线
html
<svg width="400" height="200" viewBox="0 0 400 200">
<!-- 基本直线 -->
<line x1="20" y1="20" x2="200" y2="100"
stroke="#4285f4" stroke-width="2"/>
<!-- 粗线 -->
<line x1="220" y1="20" x2="380" y2="100"
stroke="#ea4335" stroke-width="5"
stroke-linecap="round"/>
<!-- 虚线 -->
<line x1="20" y1="150" x2="380" y2="150"
stroke="#34a853" stroke-width="2"
stroke-dasharray="10, 5"/>
</svg>polyline - 折线
html
<svg width="400" height="200" viewBox="0 0 400 200">
<!-- 折线(不闭合) -->
<polyline points="20,150 60,50 100,120 140,30 180,100 220,60 260,130 300,40"
fill="none" stroke="#4285f4" stroke-width="2"
stroke-linejoin="round" stroke-linecap="round"/>
</svg>polygon - 多边形
html
<svg width="500" height="300" viewBox="0 0 500 300">
<!-- 三角形 -->
<polygon points="100,20 180,160 20,160" fill="#4285f4"/>
<!-- 五角星 -->
<polygon points="280,20 300,90 375,90 315,135 335,205 280,165 225,205 245,135 185,90 260,90"
fill="#fbbc05" stroke="#ea4335" stroke-width="1"/>
<!-- 六边形 -->
<polygon points="450,50 490,75 490,125 450,150 410,125 410,75"
fill="#34a853" opacity="0.8"/>
</svg>填充与描边
fill 属性
html
<!-- 纯色填充 -->
<rect fill="#4285f4"/>
<!-- 无填充 -->
<rect fill="none"/>
<!-- 渐变填充 -->
<rect fill="url(#myGradient)"/>
<!-- 图案填充 -->
<rect fill="url(#myPattern)"/>
<!-- 半透明填充 -->
<rect fill="rgba(66, 133, 244, 0.5)"/>stroke 属性
html
<svg width="400" height="200" viewBox="0 0 400 200">
<!-- 描边宽度 -->
<rect x="10" y="10" width="60" height="40" stroke="#4285f4" stroke-width="1"/>
<rect x="90" y="10" width="60" height="40" stroke="#4285f4" stroke-width="3"/>
<rect x="170" y="10" width="60" height="40" stroke="#4285f4" stroke-width="5"/>
<!-- 描边端点 -->
<line x1="10" y1="80" x2="100" y2="80" stroke="#ea4335" stroke-width="5" stroke-linecap="butt"/>
<line x1="120" y1="80" x2="210" y2="80" stroke="#ea4335" stroke-width="5" stroke-linecap="round"/>
<line x1="230" y1="80" x2="320" y2="80" stroke="#ea4335" stroke-width="5" stroke-linecap="square"/>
<!-- 描边连接 -->
<polyline points="10,130 50,100 90,130" fill="none" stroke="#34a853" stroke-width="5" stroke-linejoin="miter"/>
<polyline points="120,130 160,100 200,130" fill="none" stroke="#34a853" stroke-width="5" stroke-linejoin="round"/>
<polyline points="230,130 270,100 310,130" fill="none" stroke="#34a853" stroke-width="5" stroke-linejoin="bevel"/>
<!-- 虚线样式 -->
<line x1="10" y1="170" x2="350" y2="170" stroke="#9c27b0" stroke-width="2" stroke-dasharray="10,5"/>
<line x1="10" y1="190" x2="350" y2="190" stroke="#9c27b0" stroke-width="2" stroke-dasharray="5,3,2"/>
</svg>样式属性速查表
| 属性 | 说明 | 可选值 |
|---|---|---|
fill | 填充颜色 | 颜色值、none、url() |
fill-opacity | 填充透明度 | 0 ~ 1 |
stroke | 描边颜色 | 颜色值、none |
stroke-width | 描边宽度 | 数值 |
stroke-opacity | 描边透明度 | 0 ~ 1 |
stroke-linecap | 端点样式 | butt、round、square |
stroke-linejoin | 连接样式 | miter、round、bevel |
stroke-dasharray | 虚线模式 | 数值列表 |
opacity | 整体透明度 | 0 ~ 1 |
实战示例
示例 1:SVG 图标绘制
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SVG 图标</title>
<style>
svg { border: 1px solid #ccc; margin: 10px; }
</style>
</head>
<body>
<h1>SVG 图标绘制</h1>
<!-- 首页图标 -->
<svg width="48" height="48" viewBox="0 0 48 48">
<path d="M24 4L4 20h6v20h10V28h8v12h10V20h6L24 4z" fill="#4285f4"/>
</svg>
<!-- 搜索图标 -->
<svg width="48" height="48" viewBox="0 0 48 48">
<circle cx="20" cy="20" r="12" fill="none" stroke="#34a853" stroke-width="4"/>
<line x1="28" y1="28" x2="42" y2="42" stroke="#34a853" stroke-width="4" stroke-linecap="round"/>
</svg>
<!-- 设置图标(齿轮) -->
<svg width="48" height="48" viewBox="0 0 48 48">
<path d="M24 16a8 8 0 1 0 0 16 8 8 0 0 0 0-16zm0 12a4 4 0 1 1 0-8 4 4 0 0 1 0 8z" fill="#ea4335"/>
<path d="M38.86 25.94l-2.68-.74a14.07 14.07 0 0 0 0-4.4l2.68-.74a1 1 0 0 0 .72-1.22l-2.56-4.43a1 1 0 0 0-1.18-.44l-2.5 1.24a13.86 13.86 0 0 0-3.12-1.8l-.38-2.78A1 1 0 0 0 28.84 10h-5.68a1 1 0 0 0-1 .88l-.38 2.78a13.86 13.86 0 0 0-3.12 1.8l-2.5-1.24a1 1 0 0 0-1.18.44l-2.56 4.43a1 1 0 0 0 .72 1.22l2.68.74a14.07 14.07 0 0 0 0 4.4l-2.68.74a1 1 0 0 0-.72 1.22l2.56 4.43a1 1 0 0 0 1.18.44l2.5-1.24a13.86 13.86 0 0 0 3.12 1.8l.38 2.78a1 1 0 0 0 1 .88h5.68a1 1 0 0 0 1-.88l.38-2.78a13.86 13.86 0 0 0 3.12-1.8l2.5 1.24a1 1 0 0 0 1.18-.44l2.56-4.43a1 1 0 0 0-.72-1.22z"
fill="#ea4335"/>
</svg>
</body>
</html>示例 2:SVG 响应式设计
html
<!-- 使用 viewBox 实现响应式 SVG -->
<svg width="100%" height="auto" viewBox="0 0 400 300" preserveAspectRatio="xMidYMid meet">
<rect x="20" y="20" width="160" height="100" rx="10" fill="#4285f4"/>
<circle cx="300" cy="70" r="60" fill="#34a853"/>
<polygon points="200,160 260,280 140,280" fill="#ea4335"/>
</svg>preserveAspectRatio 选项
| 值 | 说明 |
|---|---|
xMidYMid meet | 等比缩放,居中显示(默认) |
xMidYMid slice | 等比缩放,裁剪溢出 |
none | 拉伸填满容器 |
xMinYMin meet | 等比缩放,左上对齐 |
注意事项
1. SVG 是 XML 格式
所有属性必须正确闭合,标签必须成对:
html
<!-- 正确 -->
<rect x="10" y="10" width="100" height="50"/>
<!-- 错误:未闭合 -->
<rect x="10" y="10" width="100" height="50">
<!-- 错误:自闭合用错 -->
<rect x="10" y="10" width="100" height="50"></Rect> <!-- 大小写错误 -->2. fill 的默认值
SVG 图形默认 fill="black",如果只需要描边,必须设置 fill="none":
html
<!-- 错误:只设置了 stroke,但 fill 默认是黑色 -->
<circle cx="50" cy="50" r="40" stroke="#4285f4" stroke-width="2"/>
<!-- 正确 -->
<circle cx="50" cy="50" r="40" fill="none" stroke="#4285f4" stroke-width="2"/>最佳实践
1. 使用 CSS 样式化 SVG
html
<style>
.icon {
fill: currentColor;
stroke: none;
transition: fill 0.2s;
}
.icon:hover {
fill: #ea4335;
}
</style>
<svg class="icon" width="24" height="24" viewBox="0 0 24 24">
<path d="M12 2L2 12h3v8h6v-5h2v5h6v-8h3L12 2z"/>
</svg>2. 使用语义化结构
html
<svg viewBox="0 0 400 300" role="img" aria-label="柱状图">
<title>月度销售额</title>
<desc>2024 年上半年销售额柱状图</desc>
<g class="chart">
<rect x="50" y="100" width="40" height="150" fill="#4285f4"/>
<rect x="110" y="80" width="40" height="170" fill="#34a853"/>
<rect x="170" y="120" width="40" height="130" fill="#ea4335"/>
<rect x="230" y="60" width="40" height="190" fill="#fbbc05"/>
</g>
</svg>下一节
继续学习:SVG 路径