SVG全家桶:从入门到精通,一文搞定可缩放矢量图形!
花了一周时间整理了这份SVG完全指南,包含88个实战案例,建议收藏!
📑 目录
- 前言:为什么你需要了解SVG?
- 一、SVG基础入门
- 1.1 SVG是什么?
- 1.2 如何在HTML中使用SVG?
- 1.3 SVG坐标系
- 二、SVG核心元素详解
- 2.1 基本形状
- 2.2 路径(Path)- SVG的灵魂
- 2.3 文本
- 三、SVG样式与CSS
- 3.1 内联样式 vs CSS样式
- 3.2 常用样式属性
- 四、SVG高级特性
- 4.1 渐变(Gradients)
- 4.2 滤镜(Filters)
- 4.3 变换(Transform)
- 五、SVG动画实战
- 5.1 SMIL动画
- 5.2 CSS动画
- 六、实战案例
- 6.1 响应式图标系统
- 6.2 加载动画
- 6.3 数据可视化 – 柱状图
- 6.4 渐变背景图案
- 七、SVG优化与最佳实践
- 7.1 文件优化
- 7.2 响应式SVG
- 7.3 性能优化技巧
- 八、SVG与CSS的高级应用
- 8.1 背景图案
- 8.2 剪裁与遮罩
- 九、SVG工具与资源
- 9.1 常用工具
- 9.2 学习资源
- 十、常见问题与解决方案
- 10.1 SVG无法显示
- 10.2 跨域问题
- 10.3 字体问题
- 结语
前言:为什么你需要了解SVG?
在2024年的前端开发中,SVG已经从一个“小众图形格式”变成了每个开发者必备的技能。无论是图标系统、数据可视化、动画效果还是复杂图形绘制,SVG都在发挥着不可替代的作用。
SVG的核心优势:
- 🚀 无限缩放不失真
- 📦 体积小,可压缩
- 🎨 完全可控,支持CSS和JS交互
- ♿ 无障碍支持友好
- 🔍 SEO友好,可被搜索引擎索引
一、SVG基础入门
1.1 SVG是什么?
SVG(Scalable Vector Graphics)是一种基于XML的矢量图形格式。与JPEG、PNG等位图不同,SVG使用数学公式来描述图形,因此可以无限放大而不失真。
1.2 如何在HTML中使用SVG?
<!– 方式1:直接内联 –>
<svg width="100" height="100" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="red" />
</svg>
<!– 方式2:使用img标签 –>
<img src="image.svg" alt="SVG图片" />
<!– 方式3:使用object标签 –>
<object data="image.svg" type="image/svg+xml"></object>
<!– 方式4:使用iframe –>
<iframe src="image.svg"></iframe>
1.3 SVG坐标系
SVG使用二维坐标系,原点在左上角:
- X轴:向右为正
- Y轴:向下为正
- 单位:默认使用像素(px)
二、SVG核心元素详解
2.1 基本形状
<svg width="400" height="300" xmlns="http://www.w3.org/2000/svg">
<!– 矩形 –>
<rect x="10" y="10" width="80" height="60" fill="#FF6B6B" rx="5" />
<!– 圆形 –>
<circle cx="150" cy="40" r="30" fill="#4ECDC4" />
<!– 椭圆 –>
<ellipse cx="250" cy="40" rx="40" ry="20" fill="#45B7D1" />
<!– 直线 –>
<line x1="10" y1="90" x2="100" y2="140" stroke="#333" stroke-width="3" />
<!– 折线 –>
<polyline points="120,90 150,140 180,90 210,140" fill="none" stroke="#FF6B6B" stroke-width="3" />
<!– 多边形 –>
<polygon points="250,90 290,140 270,190 230,190 210,140" fill="#FFE66D" stroke="#333" stroke-width="2" />
</svg>
2.2 路径(Path)- SVG的灵魂
Path是SVG中最强大的元素,可以绘制任意图形:
<!– 路径命令 –>
<!– M = moveto, L = lineto, H = horizontal, V = vertical –>
<!– C = curveto, S = smooth, Q = quadratic, T = smooth quadratic –>
<!– A = arc, Z = closepath –>
<svg width="400" height="200">
<!– 三角形 –>
<path d="M 10 10 L 100 10 L 55 80 Z" fill="#FF6B6B" />
<!– 贝塞尔曲线 –>
<path d="M 120 80 C 150 10, 200 10, 230 80" stroke="#4ECDC4" stroke-width="3" fill="none" />
<!– 弧线 –>
<path d="M 250 80 A 40 40 0 1 1 330 80" fill="none" stroke="#45B7D1" stroke-width="3" />
</svg>
2.3 文本
<svg width="400" height="150">
<text x="20" y="40" font-family="Arial" font-size="24" fill="#333">
我是SVG文本
</text>
<!– 带样式的文本 –>
<text x="20" y="80" font-family="Arial" font-size="20" fill="#FF6B6B" font-weight="bold" text-decoration="underline">
带样式的文本
</text>
<!– 沿路径文本 –>
<path id="textPath" d="M 20 120 Q 100 80 180 120" fill="none" stroke="#ccc" />
<text font-family="Arial" font-size="16" fill="#45B7D1">
<textPath href="#textPath">我是沿路径的文字</textPath>
</text>
</svg>
三、SVG样式与CSS
3.1 内联样式 vs CSS样式
<!– 内联样式 –>
<circle cx="50" cy="50" r="30" fill="red" stroke="blue" stroke-width="3" />
<!– 使用style属性 –>
<circle cx="150" cy="50" r="30" style="fill: red; stroke: blue; stroke-width: 3;" />
<!– 使用CSS类 –>
<style>
.my-circle {
fill: red;
stroke: blue;
stroke-width: 3;
transition: all 0.3s;
}
.my-circle:hover {
fill: blue;
stroke: red;
transform: scale(1.2);
}
</style>
<circle cx="250" cy="50" r="30" class="my-circle" />
3.2 常用样式属性
| fill | 填充颜色 | red, #FF0000, rgb(255,0,0) |
| stroke | 描边颜色 | blue |
| stroke-width | 描边宽度 | 2, 3px |
| stroke-opacity | 描边透明度 | 0.5 |
| fill-opacity | 填充透明度 | 0.8 |
| opacity | 整体透明度 | 0.9 |
四、SVG高级特性
4.1 渐变(Gradients)
<svg width="400" height="200">
<defs>
<!– 线性渐变 –>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#FF6B6B;stop-opacity:1" />
<stop offset="100%" style="stop-color:#4ECDC4;stop-opacity:1" />
</linearGradient>
<!– 径向渐变 –>
<radialGradient id="grad2" cx="50%" cy="50%" r="50%">
<stop offset="0%" style="stop-color:#FFE66D" />
<stop offset="100%" style="stop-color:#FF6B6B" />
</radialGradient>
</defs>
<rect x="10" y="10" width="180" height="80" fill="url(#grad1)" rx="10" />
<circle cx="300" cy="50" r="40" fill="url(#grad2)" />
</svg>
4.2 滤镜(Filters)
<svg width="400" height="200">
<defs>
<!– 模糊滤镜 –>
<filter id="blur">
<feGaussianBlur stdDeviation="3" />
</filter>
<!– 阴影滤镜 –>
<filter id="shadow">
<feDropShadow dx="3" dy="3" stdDeviation="3" flood-color="#000" flood-opacity="0.5" />
</filter>
</defs>
<circle cx="80" cy="80" r="40" fill="#FF6B6B" filter="url(#blur)" />
<circle cx="250" cy="80" r="40" fill="#4ECDC4" filter="url(#shadow)" />
</svg>
4.3 变换(Transform)
<svg width="400" height="200">
<!– 旋转 –>
<rect x="50" y="20" width="60" height="40" fill="#FF6B6B" transform="rotate(45, 80, 40)" />
<!– 缩放 –>
<rect x="150" y="20" width="60" height="40" fill="#4ECDC4" transform="scale(1.5, 0.8)" />
<!– 平移 –>
<rect x="250" y="20" width="60" height="40" fill="#45B7D1" transform="translate(20, 30)" />
</svg>
五、SVG动画实战
5.1 SMIL动画
<svg width="400" height="200">
<!– 基本动画 –>
<circle cx="50" cy="100" r="20" fill="#FF6B6B">
<animate attributeName="cx" from="50" to="350" dur="2s" repeatCount="indefinite" />
</circle>
<!– 颜色变化 –>
<circle cy="100" r="20" fill="#4ECDC4">
<animate attributeName="cx" values="50;350;50" dur="3s" repeatCount="indefinite" />
<animate attributeName="fill" values="#4ECDC4;#FFE66D;#4ECDC4" dur="3s" repeatCount="indefinite" />
</circle>
<!– 旋转动画 –>
<rect x="0" y="0" width="40" height="40" fill="#45B7D1" transform-origin="300 100">
<animateTransform attributeName="transform" type="rotate" from="0 300 100" to="360 300 100" dur="2s" repeatCount="indefinite" />
</rect>
</svg>
5.2 CSS动画
<style>
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-50px); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
}
.bounce {
animation: bounce 1s ease-in-out infinite;
}
.pulse {
animation: pulse 1.5s ease-in-out infinite;
transform-origin: center;
}
</style>
<svg width="400" height="200">
<circle cx="100" cy="100" r="30" fill="#FF6B6B" class="bounce" />
<circle cx="250" cy="100" r="30" fill="#4ECDC4" class="pulse" />
</svg>
六、实战案例
6.1 响应式图标系统
<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!– 搜索图标 –>
<circle cx="11" cy="11" r="8" />
<line x1="21" y1="21" x2="16.65" y2="16.65" />
</svg>
<svg viewBox="0 0 24 24" width="32" height="32" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!– 心形图标 –>
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
</svg>
6.2 加载动画
<svg width="120" height="120" viewBox="0 0 120 120">
<circle cx="60" cy="60" r="50" fill="none" stroke="#e0e0e0" stroke-width="8" />
<circle cx="60" cy="60" r="50" fill="none" stroke="#4ECDC4" stroke-width="8"
stroke-linecap="round" stroke-dasharray="314" stroke-dashoffset="314">
<animate attributeName="stroke-dashoffset" from="314" to="0" dur="2s" repeatCount="indefinite" />
<animateTransform attributeName="transform" type="rotate" from="0 60 60" to="360 60 60" dur="2s" repeatCount="indefinite" />
</circle>
</svg>
6.3 数据可视化 – 柱状图
<svg width="400" height="300">
<!– 背景网格 –>
<rect width="400" height="300" fill="#f8f9fa" />
<!– Y轴网格线 –>
<line x1="60" y1="30" x2="360" y2="30" stroke="#dee2e6" stroke-width="1" />
<line x1="60" y1="80" x2="360" y2="80" stroke="#dee2e6" stroke-width="1" />
<line x1="60" y1="130" x2="360" y2="130" stroke="#dee2e6" stroke-width="1" />
<line x1="60" y1="180" x2="360" y2="180" stroke="#dee2e6" stroke-width="1" />
<line x1="60" y1="230" x2="360" y2="230" stroke="#dee2e6" stroke-width="1" />
<!– 柱状图 –>
<g transform="translate(60, 20)">
<!– 柱子1 –>
<rect x="30" y="100" width="40" height="150" fill="#FF6B6B" rx="4">
<animate attributeName="height" from="0" to="150" dur="1s" fill="freeze" />
<animate attributeName="y" from="250" to="100" dur="1s" fill="freeze" />
</rect>
<text x="50" y="270" text-anchor="middle" font-size="12" fill="#666">周一</text>
<text x="50" y="90" text-anchor="middle" font-size="14" fill="#FF6B6B" font-weight="bold">85</text>
<!– 柱子2 –>
<rect x="90" y="70" width="40" height="180" fill="#4ECDC4" rx="4">
<animate attributeName="height" from="0" to="180" dur="1s" fill="freeze" />
<animate attributeName="y" from="250" to="70" dur="1s" fill="freeze" />
</rect>
<text x="110" y="270" text-anchor="middle" font-size="12" fill="#666">周二</text>
<text x="110" y="60" text-anchor="middle" font-size="14" fill="#4ECDC4" font-weight="bold">95</text>
<!– 柱子3 –>
<rect x="150" y="130" width="40" height="120" fill="#45B7D1" rx="4">
<animate attributeName="height" from="0" to="120" dur="1s" fill="freeze" />
<animate attributeName="y" from="250" to="130" dur="1s" fill="freeze" />
</rect>
<text x="170" y="270" text-anchor="middle" font-size="12" fill="#666">周三</text>
<text x="170" y="120" text-anchor="middle" font-size="14" fill="#45B7D1" font-weight="bold">75</text>
<!– 柱子4 –>
<rect x="210" y="40" width="40" height="210" fill="#FFE66D" rx="4">
<animate attributeName="height" from="0" to="210" dur="1s" fill="freeze" />
<animate attributeName="y" from="250" to="40" dur="1s" fill="freeze" />
</rect>
<text x="230" y="270" text-anchor="middle" font-size="12" fill="#666">周四</text>
<text x="230" y="30" text-anchor="middle" font-size="14" fill="#FFE66D" font-weight="bold">110</text>
<!– 柱子5 –>
<rect x="270" y="85" width="40" height="165" fill="#FF9F43" rx="4">
<animate attributeName="height" from="0" to="165" dur="1s" fill="freeze" />
<animate attributeName="y" from="250" to="85" dur="1s" fill="freeze" />
</rect>
<text x="290" y="270" text-anchor="middle" font-size="12" fill="#666">周五</text>
<text x="290" y="75" text-anchor="middle" font-size="14" fill="#FF9F43" font-weight="bold">90</text>
</g>
<!– 坐标轴 –>
<line x1="60" y1="250" x2="370" y2="250" stroke="#333" stroke-width="2" />
<line x1="60" y1="20" x2="60" y2="250" stroke="#333" stroke-width="2" />
<!– 标题 –>
<text x="200" y="290" text-anchor="middle" font-size="16" fill="#333" font-weight="bold">
本周访问量统计
</text>
</svg>
6.4 渐变背景图案
<svg width="400" height="200">
<defs>
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#667eea" />
<stop offset="100%" style="stop-color:#764ba2" />
</linearGradient>
<linearGradient id="textGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#f093fb" />
<stop offset="100%" style="stop-color:#f5576c" />
</linearGradient>
</defs>
<rect width="400" height="200" fill="url(#bgGrad)" rx="15" />
<text x="200" y="100" text-anchor="middle" font-size="36" font-weight="bold" fill="url(#textGrad)" dominant-baseline="middle">
渐变文字
</text>
<text x="200" y="140" text-anchor="middle" font-size="16" fill="rgba(255,255,255,0.8)">
SVG渐变应用示例
</text>
</svg>
七、SVG优化与最佳实践
7.1 文件优化
// 使用SVGO进行优化
const svgo = new SVGO({
plugins: [
{ removeDoctype: true },
{ removeXMLProcInst: true },
{ removeComments: true },
{ removeMetadata: true },
{ removeEditorsNSData: true },
{ cleanupAttrs: true },
{ mergeStyles: true },
{ inlineStyles: true },
{ minifyStyles: true },
{ cleanupIDs: true },
{ removeUselessDefs: true },
{ cleanupNumericValues: true },
{ convertColors: true },
{ removeUnknownsAndDefaults: true },
{ removeNonInheritableGroupAttrs: true },
{ removeUselessStrokeAndFill: true },
{ removeViewBox: false },
{ cleanupEnableBackground: true },
{ removeHiddenElems: true },
{ removeEmptyText: true },
{ convertShapeToPath: true },
{ moveElemsAttrsToGroup: true },
{ moveGroupAttrsToElems: true },
{ collapseGroups: true },
{ convertPathData: true },
{ convertTransform: true },
{ removeEmptyAttrs: true },
{ removeEmptyContainers: true },
{ mergePaths: true },
{ removeUnusedNS: true },
{ sortAttrs: true },
{ removeTitle: true },
{ removeDesc: true },
{ removeDimensions: true }
]
});
7.2 响应式SVG
<!– 使用viewBox实现响应式 –>
<svg viewBox="0 0 100 100" width="100%" height="auto">
<circle cx="50" cy="50" r="40" fill="#FF6B6B" />
</svg>
<!– 使用媒体查询 –>
<style>
.responsive-svg {
max-width: 100%;
height: auto;
}
@media (max-width: 600px) {
.responsive-svg {
transform: scale(0.8);
}
}
</style>
7.3 性能优化技巧
八、SVG与CSS的高级应用
8.1 背景图案
<style>
.pattern-bg {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Crect width='40' height='40' fill='%23f0f0f0'/%3E%3Ccircle cx='20' cy='20' r='2' fill='%23ccc'/%3E%3C/svg%3E");
height: 200px;
padding: 20px;
}
</style>
<div class="pattern-bg">
<h3>SVG背景图案</h3>
<p>使用SVG作为CSS背景图案</p>
</div>
8.2 剪裁与遮罩
<svg width="400" height="300">
<defs>
<!– 剪裁路径 –>
<clipPath id="clip">
<circle cx="200" cy="150" r="100" />
</clipPath>
<!– 遮罩 –>
<mask id="mask">
<rect width="400" height="300" fill="white" />
<circle cx="200" cy="150" r="80" fill="black" />
</mask>
</defs>
<!– 原始图片 –>
<image href="image.jpg" width="400" height="300" />
<!– 剪裁后的图片 –>
<image href="image.jpg" width="400" height="300" clip-path="url(#clip)" transform="translate(0, -50)" />
<!– 遮罩效果 –>
<rect width="400" height="300" fill="#FF6B6B" mask="url(#mask)" />
</svg>
九、SVG工具与资源
9.1 常用工具
| SVGO | SVG优化压缩 | github.com/svg/svgo |
| SVGOMG | 在线优化工具 | jakearchibald.github.io/svgomg |
| Boxy SVG | 图形编辑器 | boxy-svg.com |
| Figma | UI设计工具 | figma.com |
| Illustrator | 专业矢量图工具 | adobe.com/products/illustrator |
9.2 学习资源
- MDN Web Docs:developer.mozilla.org/SVG
- SVG Patterns:heropatterns.com
- SVG Backgrounds:svgbackgrounds.com
- CSS-Tricks SVG:css-tricks.com/tag/svg
- SVG.js:svgjs.com
十、常见问题与解决方案
10.1 SVG无法显示
<!– 检查命名空间 –>
<svg xmlns="http://www.w3.org/2000/svg" …>
<!– 检查文件格式 –>
<!– 确保是纯文本格式,不是二进制 –>
10.2 跨域问题
<!– 使用data URI –>
<img src="data:image/svg+xml;utf8,<svg …></svg>" />
<!– 或者使用CORS配置 –>
<img src="image.svg" crossorigin="anonymous" />
10.3 字体问题
<!– 使用系统字体 –>
<text font-family="Arial, Helvetica, sans-serif">
<!– 使用web字体 –>
<style>
@font-face {
font-family: 'CustomFont';
src: url('font.woff2');
}
</style>
<text font-family="CustomFont">
结语
SVG是一个强大而灵活的技术,掌握它可以让你的Web开发技能更上一层楼。从简单的图标到复杂的数据可视化,从基础的图形绘制到高级的动画效果,SVG都能胜任。
希望这篇SVG全家桶能帮助你快速掌握SVG的核心知识,在实际项目中得心应手。如果你有任何问题或建议,欢迎在评论区留言交流!
作者:人民广场吃泡面 原文链接:https://blog.csdn.net/nxiaotan/article/details/164061459?spm=1001.2014.3001.5501 版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明。
如果觉得有帮助,请点赞收藏支持一下!👍
