SVG(Scalable Vector Graphics,可缩放矢量图形)是一种基于XML的矢量图形格式。与Canvas的位图不同,SVG图形在放大或缩小时不会失真,非常适合图标、图表、地图等应用场景。
东巴文(db-w.cn) 认为:SVG是Web图形技术的瑰宝,矢量特性让它成为响应式设计的理想选择。
| 特点 | 说明 |
|---|---|
| 矢量图形 | 放大缩小不失真 |
| 文件小 | 适合简单图形 |
| 可搜索 | 文本可被搜索引擎索引 |
| 可样式化 | 支持CSS样式 |
| 可动画 | 支持SMIL动画 |
| 可交互 | 支持JavaScript操作 |
| 特性 | SVG | Canvas |
|---|---|---|
| 图形类型 | 矢量图形 | 位图图形 |
| 缩放 | 不失真 | 会失真 |
| 性能 | 适合少量图形 | 适合大量图形 |
| 事件处理 | 每个元素可添加事件 | 需要手动计算 |
| 适用场景 | 图标、图表、地图 | 游戏、图像处理 |
东巴文点评:SVG和Canvas各有优势,选择哪种技术取决于具体应用场景。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>内联SVG示例</title>
</head>
<body>
<svg width="200" height="200">
<circle cx="100" cy="100" r="50" fill="blue"/>
</svg>
</body>
</html>
<img src="image.svg" alt="SVG图像" width="200" height="200">
.icon {
width: 32px;
height: 32px;
background-image: url('icon.svg');
background-size: contain;
}
<object type="image/svg+xml" data="image.svg" width="200" height="200">
您的浏览器不支持SVG
</object>
<iframe src="image.svg" width="200" height="200"></iframe>
东巴文点评:内联SVG最灵活,可以通过CSS和JavaScript完全控制;img标签引入最简单,但功能受限。
<svg width="300" height="200">
<!-- 基本矩形 -->
<rect x="10" y="10" width="100" height="80" fill="blue"/>
<!-- 圆角矩形 -->
<rect x="120" y="10" width="100" height="80" rx="10" ry="10" fill="green"/>
<!-- 带边框矩形 -->
<rect x="10" y="100" width="100" height="80" fill="yellow" stroke="red" stroke-width="3"/>
</svg>
属性说明:
| 属性 | 说明 |
|---|---|
x |
左上角X坐标 |
y |
左上角Y坐标 |
width |
宽度 |
height |
高度 |
rx |
水平圆角半径 |
ry |
垂直圆角半径 |
<svg width="300" height="200">
<circle cx="100" cy="100" r="50" fill="purple"/>
<circle cx="200" cy="100" r="40" fill="orange" stroke="black" stroke-width="2"/>
</svg>
属性说明:
| 属性 | 说明 |
|---|---|
cx |
圆心X坐标 |
cy |
圆心Y坐标 |
r |
半径 |
<svg width="300" height="200">
<ellipse cx="150" cy="100" rx="100" ry="50" fill="cyan"/>
</svg>
属性说明:
| 属性 | 说明 |
|---|---|
cx |
圆心X坐标 |
cy |
圆心Y坐标 |
rx |
水平半径 |
ry |
垂直半径 |
<svg width="300" height="200">
<line x1="10" y1="10" x2="200" y2="150" stroke="red" stroke-width="3"/>
</svg>
属性说明:
| 属性 | 说明 |
|---|---|
x1 |
起点X坐标 |
y1 |
起点Y坐标 |
x2 |
终点X坐标 |
y2 |
终点Y坐标 |
<svg width="300" height="200">
<polyline points="10,10 50,100 100,50 150,120 200,80"
fill="none" stroke="blue" stroke-width="2"/>
</svg>
<svg width="300" height="200">
<!-- 三角形 -->
<polygon points="100,10 150,100 50,100" fill="red"/>
<!-- 五角星 -->
<polygon points="200,10 220,80 290,80 235,120 255,190 200,150 145,190 165,120 110,80 180,80"
fill="yellow" stroke="orange" stroke-width="2"/>
</svg>
东巴文点评:polyline和polygon的区别在于,polygon会自动闭合路径。
path是SVG中最强大的绘图元素,可以绘制任意形状。
<svg width="300" height="200">
<!-- 三角形 -->
<path d="M 100 10 L 150 100 L 50 100 Z" fill="green"/>
<!-- 曲线 -->
<path d="M 200 10 Q 250 100 200 150" fill="none" stroke="blue" stroke-width="2"/>
</svg>
路径命令:
| 命令 | 说明 | 参数 |
|---|---|---|
M |
移动到 | x y |
L |
连线到 | x y |
H |
水平连线 | x |
V |
垂直连线 | y |
C |
三次贝塞尔曲线 | x1 y1 x2 y2 x y |
S |
平滑三次贝塞尔曲线 | x2 y2 x y |
Q |
二次贝塞尔曲线 | x1 y1 x y |
T |
平滑二次贝塞尔曲线 | x y |
A |
椭圆弧 | rx ry x-axis-rotation large-arc-flag sweep-flag x y |
Z |
闭合路径 | - |
东巴文点评:path命令大小写有区别,大写表示绝对坐标,小写表示相对坐标。
<svg width="300" height="200">
<text x="50" y="50" font-size="24" fill="blue">东巴文SVG</text>
</svg>
<svg width="400" height="200">
<!-- 字体样式 -->
<text x="10" y="30" font-family="Arial" font-size="20" font-weight="bold" fill="black">
粗体文本
</text>
<!-- 斜体文本 -->
<text x="10" y="60" font-style="italic" font-size="20" fill="gray">
斜体文本
</text>
<!-- 文本装饰 -->
<text x="10" y="90" text-decoration="underline" font-size="20" fill="blue">
下划线文本
</text>
<!-- 文本对齐 -->
<text x="200" y="120" text-anchor="middle" font-size="20" fill="green">
居中文本
</text>
</svg>
<svg width="400" height="200">
<text x="50" y="50" font-size="20">
<tspan fill="red">红色</tspan>
<tspan fill="blue">蓝色</tspan>
<tspan fill="green">绿色</tspan>
</text>
<text x="50" y="100" font-size="20">
<tspan x="50" dy="0">第一行</tspan>
<tspan x="50" dy="25">第二行</tspan>
<tspan x="50" dy="25">第三行</tspan>
</text>
</svg>
<svg width="400" height="200">
<!-- 定义路径 -->
<defs>
<path id="myPath" d="M 50 100 Q 200 50 350 100" fill="none"/>
</defs>
<!-- 文本沿路径排列 -->
<text font-size="20">
<textPath href="#myPath">东巴文SVG文本路径示例</textPath>
</text>
</svg>
<svg width="300" height="200">
<rect x="10" y="10" width="100" height="80"
style="fill: blue; stroke: red; stroke-width: 3;"/>
</svg>
<svg width="300" height="200">
<rect x="10" y="10" width="100" height="80"
fill="blue" stroke="red" stroke-width="3"/>
</svg>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SVG CSS样式</title>
<style>
.my-rect {
fill: blue;
stroke: red;
stroke-width: 3;
}
.my-rect:hover {
fill: green;
}
</style>
</head>
<body>
<svg width="300" height="200">
<rect class="my-rect" x="10" y="10" width="100" height="80"/>
</svg>
</body>
</html>
| 属性 | 说明 | 示例 |
|---|---|---|
fill |
填充颜色 | fill="red" |
stroke |
描边颜色 | stroke="blue" |
stroke-width |
描边宽度 | stroke-width="2" |
stroke-linecap |
线端样式 | stroke-linecap="round" |
stroke-linejoin |
线连接样式 | stroke-linejoin="round" |
opacity |
透明度 | opacity="0.5" |
fill-opacity |
填充透明度 | fill-opacity="0.5" |
stroke-opacity |
描边透明度 | stroke-opacity="0.5" |
东巴文点评:SVG样式优先级:内联样式 > CSS样式 > 属性样式。
<svg width="300" height="200">
<defs>
<linearGradient id="linearGradient1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="yellow"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
</defs>
<rect x="10" y="10" width="200" height="100" fill="url(#linearGradient1)"/>
</svg>
<svg width="300" height="200">
<defs>
<radialGradient id="radialGradient1" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="white"/>
<stop offset="50%" stop-color="yellow"/>
<stop offset="100%" stop-color="red"/>
</radialGradient>
</defs>
<circle cx="150" cy="100" r="80" fill="url(#radialGradient1)"/>
</svg>
东巴文点评:渐变必须定义在<defs>元素中,并通过id引用。
<svg width="300" height="200">
<defs>
<pattern id="pattern1" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="5" fill="blue"/>
</pattern>
</defs>
<rect x="10" y="10" width="200" height="150" fill="url(#pattern1)"/>
</svg>
| 属性 | 说明 |
|---|---|
x |
图案起始X坐标 |
y |
图案起始Y坐标 |
width |
图案宽度 |
height |
图案高度 |
patternUnits |
图案单位(userSpaceOnUse/objectBoundingBox) |
<svg width="300" height="200">
<defs>
<filter id="blur1">
<feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
</filter>
</defs>
<rect x="10" y="10" width="100" height="80" fill="blue" filter="url(#blur1)"/>
</svg>
<svg width="300" height="200">
<defs>
<filter id="shadow1" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="5" dy="5" stdDeviation="3" flood-color="black" flood-opacity="0.5"/>
</filter>
</defs>
<rect x="50" y="50" width="100" height="80" fill="blue" filter="url(#shadow1)"/>
</svg>
东巴文点评:SVG滤镜功能强大,可以实现各种图像处理效果。
<svg width="300" height="200">
<!-- 平移 -->
<rect x="10" y="10" width="50" height="50" fill="red" transform="translate(50, 50)"/>
<!-- 旋转 -->
<rect x="100" y="10" width="50" height="50" fill="blue" transform="rotate(45, 125, 35)"/>
<!-- 缩放 -->
<rect x="200" y="10" width="50" height="50" fill="green" transform="scale(1.5)"/>
<!-- 组合变换 -->
<rect x="10" y="100" width="50" height="50" fill="purple"
transform="translate(100, 0) rotate(30) scale(1.2)"/>
</svg>
| 方法 | 说明 | 示例 |
|---|---|---|
translate(tx, ty) |
平移 | transform="translate(50, 50)" |
rotate(angle, cx, cy) |
旋转 | transform="rotate(45, 100, 100)" |
scale(sx, sy) |
缩放 | transform="scale(1.5)" |
skewX(angle) |
X轴倾斜 | transform="skewX(30)" |
skewY(angle) |
Y轴倾斜 | transform="skewY(30)" |
matrix(a,b,c,d,e,f) |
矩阵变换 | transform="matrix(1,0,0,1,50,50)" |
<svg width="300" height="200">
<!-- 矩形移动动画 -->
<rect x="10" y="10" width="50" height="50" fill="blue">
<animate attributeName="x" from="10" to="200" dur="3s" repeatCount="indefinite"/>
</rect>
<!-- 圆形缩放动画 -->
<circle cx="150" cy="100" r="20" fill="red">
<animate attributeName="r" from="20" to="50" dur="2s" repeatCount="indefinite"/>
</circle>
<!-- 颜色变化动画 -->
<rect x="10" y="100" width="50" height="50">
<animate attributeName="fill" from="red" to="blue" dur="3s" repeatCount="indefinite"/>
</rect>
</svg>
| 属性 | 说明 |
|---|---|
attributeName |
动画属性名 |
from |
起始值 |
to |
结束值 |
dur |
持续时间 |
repeatCount |
重复次数(indefinite表示无限) |
fill |
动画结束后的状态(freeze/remove) |
<svg width="300" height="200">
<rect x="100" y="75" width="50" height="50" fill="green">
<animateTransform attributeName="transform" type="rotate"
from="0 125 100" to="360 125 100"
dur="5s" repeatCount="indefinite"/>
</rect>
</svg>
东巴文点评:SMIL动画简单易用,但兼容性不如CSS动画和JavaScript动画。
<svg id="mySvg" width="300" height="200">
<rect id="myRect" x="10" y="10" width="100" height="80" fill="blue"/>
</svg>
<script>
const svg = document.getElementById('mySvg');
const rect = document.getElementById('myRect');
// 修改属性
rect.setAttribute('fill', 'red');
rect.setAttribute('width', '150');
</script>
const svg = document.getElementById('mySvg');
// 创建圆形
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', '150');
circle.setAttribute('cy', '100');
circle.setAttribute('r', '50');
circle.setAttribute('fill', 'green');
svg.appendChild(circle);
<svg width="300" height="200">
<rect id="myRect" x="10" y="10" width="100" height="80" fill="blue"/>
</svg>
<script>
const rect = document.getElementById('myRect');
rect.addEventListener('click', function() {
this.setAttribute('fill', 'red');
});
rect.addEventListener('mouseenter', function() {
this.setAttribute('opacity', '0.5');
});
rect.addEventListener('mouseleave', function() {
this.setAttribute('opacity', '1');
});
</script>
东巴文点评:SVG元素可以使用标准的DOM API操作,但创建元素时必须使用createElementNS方法。
<button class="btn">
<svg width="16" height="16" viewBox="0 0 16 16">
<path d="M8 0L10 6L16 8L10 10L8 16L6 10L0 8L6 6L8 0Z" fill="currentColor"/>
</svg>
收藏
</button>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SVG Sprite示例</title>
</head>
<body>
<!-- SVG定义 -->
<svg style="display: none;">
<symbol id="icon-star" viewBox="0 0 16 16">
<path d="M8 0L10 6L16 8L10 10L8 16L6 10L0 8L6 6L8 0Z"/>
</symbol>
<symbol id="icon-heart" viewBox="0 0 16 16">
<path d="M8 14s-5.5-4.5-5.5-7.5S5 2 8 5c3-3 5.5-1.5 5.5 1.5S8 14 8 14z"/>
</symbol>
</svg>
<!-- 使用图标 -->
<svg width="16" height="16">
<use href="#icon-star"/>
</svg>
<svg width="16" height="16">
<use href="#icon-heart"/>
</svg>
</body>
</html>
东巴文点评:SVG Sprite是管理图标的最佳方式,可以复用图标定义,减少代码重复。
<svg width="100%" height="auto" viewBox="0 0 300 200">
<rect x="10" y="10" width="100" height="80" fill="blue"/>
<circle cx="200" cy="100" r="50" fill="red"/>
</svg>
viewBox说明:
viewBox="min-x min-y width height"
| 参数 | 说明 |
|---|---|
min-x |
视图框左上角X坐标 |
min-y |
视图框左上角Y坐标 |
width |
视图框宽度 |
height |
视图框高度 |
<svg width="300" height="200" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
<rect x="0" y="0" width="100" height="100" fill="blue"/>
</svg>
preserveAspectRatio值:
| 值 | 说明 |
|---|---|
none |
不保持宽高比,拉伸填充 |
xMinYMin meet |
保持宽高比,左上对齐 |
xMidYMid meet |
保持宽高比,居中对齐 |
xMaxYMax meet |
保持宽高比,右下对齐 |
东巴文点评:viewBox是响应式SVG的核心,它定义了SVG的坐标系统。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG图形示例 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
svg {
border: 1px solid #ccc;
display: block;
margin: 20px 0;
}
.interactive-rect {
cursor: pointer;
transition: all 0.3s;
}
.interactive-rect:hover {
opacity: 0.7;
}
</style>
</head>
<body>
<h1>SVG图形示例</h1>
<h2>基本形状</h2>
<svg width="600" height="200" viewBox="0 0 600 200">
<rect x="10" y="10" width="100" height="80" fill="blue" rx="10"/>
<circle cx="200" cy="50" r="40" fill="red"/>
<ellipse cx="350" cy="50" rx="60" ry="30" fill="green"/>
<line x1="450" y1="10" x2="550" y2="90" stroke="purple" stroke-width="3"/>
<polygon points="500,100 520,150 480,150" fill="orange"/>
</svg>
<h2>渐变填充</h2>
<svg width="600" height="150" viewBox="0 0 600 150">
<defs>
<linearGradient id="linearGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="red"/>
<stop offset="50%" stop-color="yellow"/>
<stop offset="100%" stop-color="blue"/>
</linearGradient>
<radialGradient id="radialGrad" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="white"/>
<stop offset="100%" stop-color="blue"/>
</radialGradient>
</defs>
<rect x="10" y="10" width="250" height="100" fill="url(#linearGrad)"/>
<circle cx="450" cy="60" r="50" fill="url(#radialGrad)"/>
</svg>
<h2>动画效果</h2>
<svg width="600" height="150" viewBox="0 0 600 150">
<rect x="10" y="50" width="50" height="50" fill="blue">
<animate attributeName="x" from="10" to="500" dur="3s" repeatCount="indefinite"/>
</rect>
<circle cx="300" cy="75" r="20" fill="red">
<animate attributeName="r" from="20" to="50" dur="2s" repeatCount="indefinite"/>
</circle>
</svg>
<h2>交互式SVG</h2>
<svg width="600" height="150" viewBox="0 0 600 150" id="interactiveSvg">
<rect class="interactive-rect" id="rect1" x="50" y="30" width="100" height="80" fill="blue"/>
<rect class="interactive-rect" id="rect2" x="200" y="30" width="100" height="80" fill="green"/>
<rect class="interactive-rect" id="rect3" x="350" y="30" width="100" height="80" fill="red"/>
</svg>
<script>
// 交互式SVG示例
const rects = document.querySelectorAll('.interactive-rect');
rects.forEach(rect => {
rect.addEventListener('click', function() {
const colors = ['blue', 'green', 'red', 'yellow', 'purple', 'orange'];
const randomColor = colors[Math.floor(Math.random() * colors.length)];
this.setAttribute('fill', randomColor);
});
});
</script>
</body>
</html>
<!-- 推荐:简洁的SVG -->
<svg width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="blue"/>
</svg>
<!-- 不推荐:包含不必要的属性 -->
<svg width="100" height="100" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1">
<circle cx="50" cy="50" r="40" fill="blue"/>
</svg>
<style>
.icon {
width: 24px;
height: 24px;
fill: currentColor;
}
.icon:hover {
fill: blue;
}
</style>
<svg class="icon" viewBox="0 0 24 24">
<path d="M12 2L15 8L22 9L17 14L18 21L12 18L6 21L7 14L2 9L9 8L12 2Z"/>
</svg>
<style>
.responsive-svg {
width: 100%;
height: auto;
}
</style>
<svg class="responsive-svg" viewBox="0 0 300 200">
<!-- SVG内容 -->
</svg>
问题1:SVG中用于定义可重用元素的元素是?
A. <use>
B. <defs>
C. <symbol>
D. <g>
答案:B
东巴文解释:<defs>元素用于定义可重用的元素,如渐变、图案、滤镜等,这些元素不会直接显示,但可以被其他元素引用。
问题2:以下哪个属性用于控制SVG的缩放行为?
A. width
B. height
C. viewBox
D. preserveAspectRatio
答案:C
东巴文解释:viewBox属性定义了SVG的坐标系统和缩放行为,是实现响应式SVG的关键属性。
任务:创建一个SVG图标,实现鼠标悬停时颜色变化的效果。
<details> <summary>点击查看参考答案</summary><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SVG图标示例</title>
<style>
.icon {
width: 48px;
height: 48px;
fill: gray;
cursor: pointer;
transition: fill 0.3s;
}
.icon:hover {
fill: #f39c12;
}
</style>
</head>
<body>
<svg class="icon" viewBox="0 0 24 24">
<path d="M12 2L15 8L22 9L17 14L18 21L12 18L6 21L7 14L2 9L9 8L12 2Z"/>
</svg>
</body>
</html>
</details>
东巴文(db-w.cn) - 让编程学习更有趣、更高效!