SVG 教程

SVG(Scalable Vector Graphics,可缩放矢量图形)是一种基于 XML 的矢量图形格式,用于在网页上绘制直线、曲线、形状、文字等,并且任意缩放不失真。

矢量图 vs 位图

对比项SVG(矢量)PNG/JPG(位图)
缩放任意缩放不失真放大模糊、有锯齿
体积图形简单时很小固定像素,一般较大
编辑代码/编辑器可改需图像软件
动画支持(CSS/SMIL)不支持
适用图标、Logo、图表、插画照片、复杂图像

SVG 的优点

  • 清晰:Retina 屏上依然锐利
  • 可编程:可被 JS/CSS 操作、动画
  • 小体积:文本格式,可 gzip 压缩
  • 无障碍:可加 title/desc 描述

一个最简单的 SVG

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

它绘制了一个圆心在 (50,50)、半径 40 的红色圆。

SVG 的应用场景

  • 网站 Logo、图标系统
  • 数据可视化(ECharts 底层)
  • 图表、地图、动效插画
  • UI 组件(进度环、图标按钮)
💡 提示

SVG 可以直接写在 HTML 中(内联),也可以作为 .svg 文件引用,还能用 <img>、CSS background 加载。

SVG 简介

本节介绍 SVG 的基本概念:坐标系、画布、与 HTML 的关系,以及浏览器的支持情况。

SVG 的坐标系

SVG 使用笛卡尔坐标系,但 y 轴向下:

  • 原点 (0,0) 在画布左上角
  • x 向右增大,y 向下增大
  • 单位默认是像素(px)
<svg width="200" height="200">
  <!-- (50,50) 距离左上角 50px 处 -->
  <rect x="50" y="50" width="100" height="80" fill="skyblue" />
</svg>

SVG 的历史

  • 1999 年 W3C 提出规范
  • 2011 年成为 W3C 推荐标准
  • SVG 2.0 仍在演进(2018 草案)
  • 现代浏览器全部支持

SVG 元素 vs HTML 元素

对比项SVGHTML
用途绘制图形页面结构
命名空间W3C SVGHTML
标签circle/rect/pathdiv/span/p
样式fill/strokecolor/background

SVG 的三种使用方式

<!-- 1. 内联 -->
<svg><circle cx="10" cy="10" r="5"/></svg>

<!-- 2. img 引用 -->
<img src="icon.svg" alt="图标">

<!-- 3. CSS 背景 -->
<div style="background: url(icon.svg)"></div>

viewBox 视口

viewBox 定义内部坐标系,让图形可缩放适配容器:

<!-- 内部逻辑坐标 0-100,放大显示在 200px 容器中 -->
<svg width="200" height="200" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="red"/>
</svg>
💡 提示

内联 SVG 可以直接用 CSS 设置样式和动画,这是 <img> 方式做不到的。

SVG VSCode

本节介绍在 VS Code 中开发 SVG 的环境搭建:编辑、预览、调试一站完成。

1. 创建文件

在 VS Code 中新建 .svg 文件,编写图形代码。

2. 安装插件

插件作用
SVG(jock)语法高亮、智能提示
SVG Preview实时预览
SVG Viewer图形化查看
Emmet(内置)快速输入标签

3. 实时预览

安装 SVG Preview 后,按 Cmd/Ctrl + Shift + V 或右键 → Open Preview,即可边写边看效果。

4. 基础模板

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="200" viewBox="0 0 300 200">
  <rect x="10" y="10" width="280" height="180" rx="8" fill="#f5f5f5" stroke="#333" stroke-width="2"/>
  <text x="150" y="100" text-anchor="middle" font-size="20" fill="#333">Hello SVG</text>
</svg>

5. 在 HTML 中调试

也可以直接在 HTML 文件中内联 SVG 并打开浏览器调试:

<!DOCTYPE html>
<html>
<body>
  <svg width="200" height="200">
    <circle cx="100" cy="100" r="80" fill="orange"/>
  </svg>
</body>
</html>
💡 提示

浏览器开发者工具也能调试内联 SVG:选中元素查看属性,动态修改样式和坐标,实时看到效果。

SVG 基本语法

SVG 的基本语法非常直观:每个图形元素由标签名 + 属性构成,属性决定位置、尺寸和样式。

基本语法结构

<svg width="400" height="300">
  <!-- 属性:x/y 位置,width/height 尺寸,fill 填充色 -->
  <rect x="20" y="20" width="150" height="100" fill="steelblue" />
  <!-- 属性:cx/cy 圆心,r 半径 -->
  <circle cx="250" cy="70" r="50" fill="tomato" />
</svg>

通用属性

属性说明示例
fill填充颜色fill="red"
stroke描边颜色stroke="black"
stroke-width描边宽度stroke-width="2"
opacity整体透明度opacity="0.5"
transform变换(平移/旋转/缩放)transform="rotate(45)"

颜色表示

<circle cx="30" cy="30" r="20" fill="red" />              <!-- 颜色名 -->
<circle cx="80" cy="30" r="20" fill="#ff0000" />          <!-- 十六进制 -->
<circle cx="130" cy="30" r="20" fill="rgb(255,0,0)" />    <!-- RGB -->
<circle cx="180" cy="30" r="20" fill="rgba(255,0,0,0.5)" /> <!-- 带透明度 -->

注释

<!-- 这是 SVG 注释 -->

大小写敏感

SVG 是 XML,标签和属性名区分大小写,且属性值建议加引号。

<!-- 正确 -->
<circle cx="50" cy="50" r="40"/>

<!-- 错误:标签名大小写不对 -->
<Circle cx="50" cy="50" r="40"/>
💡 提示

自闭合写法 <rect ... /> 在 XML/SVG 中是规范;在 HTML5 中不写斜杠也兼容。

SVG 在 HTML 中

SVG 可以直接嵌入 HTML,与页面元素无缝交互,这是它最重要的使用方式。

内联 SVG

<!DOCTYPE html>
<html>
<body>
  <h1>我的 SVG 图标</h1>
  <svg width="60" height="60" viewBox="0 0 60 60">
    <circle cx="30" cy="30" r="25" fill="#4CAF50"/>
    <text x="30" y="38" text-anchor="middle" fill="white" font-size="24">✓</text>
  </svg>
</body>
</html>

用 CSS 控制内联 SVG

内联 SVG 的元素可以直接被 CSS 选中和样式化:

<style>
  .icon { width: 48px; height: 48px; }
  .icon:hover circle { fill: #ff9800; }   /* 悬停变色 */
  .icon circle { transition: fill 0.3s; }
</style>

<svg class="icon" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#2196F3"/>
</svg>

img 方式引用

<img src="logo.svg" width="100" height="100" alt="Logo">

CSS 背景方式

.btn {
  background: url("arrow.svg") no-repeat center;
  background-size: 20px 20px;
}

三种方式对比

方式CSS 控制JS 控制适用
内联✅✅需要交互/动画
img仅整体仅整体静态图标
CSS 背景✅❌装饰性图形
💡 提示

内联 SVG 里的元素可通过 document.querySelector 获取并操作,与操作普通 HTML 元素一样。

SVG 矩形

矩形(<rect>)是最基础的 SVG 形状之一,支持圆角。

基本矩形

<svg width="300" height="150">
  <rect x="20" y="20" width="200" height="100" fill="steelblue" />
</svg>

圆角矩形

<svg width="300" height="150">
  <!-- rx/ry 控制圆角半径 -->
  <rect x="20" y="20" width="200" height="100" rx="20" ry="20" fill="#FFC107" />
</svg>

只填充 / 只描边 / 填充+描边

<svg width="400" height="120">
  <rect x="10" y="10" width="100" height="80" fill="lightgreen" />
  <rect x="140" y="10" width="100" height="80" fill="none" stroke="crimson" stroke-width="3" />
  <rect x="270" y="10" width="100" height="80" fill="lightblue" stroke="navy" stroke-width="2" />
</svg>

透明度

<svg width="300" height="120">
  <rect x="20" y="20" width="100" height="80" fill="red" opacity="1" />
  <rect x="60" y="20" width="100" height="80" fill="red" opacity="0.5" />
  <rect x="100" y="20" width="100" height="80" fill="red" opacity="0.2" />
</svg>

rect 全部属性

属性说明
x / y左上角坐标(默认 0)
width / height宽高(必填)
rx / ry圆角半径(x/y 方向)
fill填充色(默认黑色)
stroke / stroke-width描边色/宽度
💡 提示

只设 rx 不设 ry 时,ry 默认等于 rx,画正圆角。

SVG 圆形

圆形(<circle>)用圆心和半径定义,是绘制点的理想选择。

基本圆形

<svg width="200" height="200">
  <!-- cx/cy 圆心,r 半径 -->
  <circle cx="100" cy="100" r="80" fill="#E91E63" />
</svg>

空心圆(描边)

<svg width="200" height="200">
  <circle cx="100" cy="100" r="70" fill="none" stroke="#3F51B5" stroke-width="10" />
</svg>

多个圆组合(奥运五环风格)

<svg width="300" height="150">
  <circle cx="80" cy="60" r="40" fill="none" stroke="#4285F4" stroke-width="8"/>
  <circle cx="150" cy="60" r="40" fill="none" stroke="#EA4335" stroke-width="8"/>
  <circle cx="220" cy="60" r="40" fill="none" stroke="#FBBC05" stroke-width="8"/>
</svg>

渐变圆

<svg width="200" height="200">
  <defs>
    <radialGradient id="grad">
      <stop offset="0%" stop-color="#fff" />
      <stop offset="100%" stop-color="#FF5722" />
    </radialGradient>
  </defs>
  <circle cx="100" cy="100" r="80" fill="url(#grad)" />
</svg>

circle 属性速查

属性说明
cx / cy圆心坐标(默认 0)
r半径(必填)
fill / stroke填充/描边
💡 提示

雷达图、进度环、头像背景等场景,圆形都是核心元素。

SVG 椭圆

椭圆(<ellipse>)与圆形类似,但 x/y 方向的半径可以不同。

基本椭圆

<svg width="300" height="200">
  <!-- rx 水平半径,ry 垂直半径 -->
  <ellipse cx="150" cy="100" rx="120" ry="60" fill="#9C27B0" />
</svg>

椭圆 vs 圆

对比项circleellipse
半径r(单一)rx + ry
形状正圆可扁可长

偏心椭圆(rx > ry)

<svg width="400" height="150">
  <ellipse cx="100" cy="75" rx="90" ry="30" fill="orange"/>
  <ellipse cx="250" cy="75" rx="30" ry="60" fill="teal"/>
</svg>

带描边的椭圆

<svg width="300" height="200">
  <ellipse cx="150" cy="100" rx="110" ry="55"
           fill="none" stroke="#00BCD4" stroke-width="4" stroke-dasharray="10 6" />
</svg>

stroke-dasharray 让描边变成虚线,第一个数字是线段长,第二个是间隔。

ellipse 属性速查

属性说明
cx / cy中心坐标(默认 0)
rx水平半径(必填)
ry垂直半径(必填)
💡 提示

当 rx == ry 时,ellipse 与 circle 效果完全相同,日常画圆推荐直接用 circle。

SVG 直线

直线(<line>)通过两个端点坐标绘制,是最简单的 SVG 图形。

基本直线

<svg width="300" height="100">
  <!-- x1 y1 起点,x2 y2 终点 -->
  <line x1="20" y1="80" x2="280" y2="20" stroke="black" stroke-width="2" />
</svg>

横线与竖线

<svg width="300" height="200">
  <!-- 水平线 -->
  <line x1="10" y1="50" x2="290" y2="50" stroke="crimson" stroke-width="2"/>
  <!-- 垂直线 -->
  <line x1="150" y1="10" x2="150" y2="190" stroke="navy" stroke-width="2" stroke-dasharray="5 5"/>
</svg>

带端点标记的直线

<svg width="300" height="100">
  <line x1="30" y1="50" x2="270" y2="50"
        stroke="#673AB7" stroke-width="3"
        stroke-linecap="round" />
</svg>

stroke-linecap:butt(平头,默认)、round(圆头)、square(方头)。

line 属性速查

属性说明
x1 / y1起点坐标(默认 0)
x2 / y2终点坐标(默认 0)
stroke颜色(必填,否则看不见)
stroke-width线宽
💡 提示

注意:<line> 没有 fill,颜色靠 stroke 设置,否则默认黑色不可见时会感觉"画不出线"。

SVG 多边形

多边形(<polygon>)通过一系列顶点坐标绘制闭合图形,自动连接首尾顶点。

基本多边形

<svg width="300" height="300">
  <!-- points:一组"x,y"坐标对 -->
  <polygon points="150,20 250,200 50,200" fill="#FF9800" />
</svg>

五角星

<svg width="300" height="300">
  <polygon points="150,10 180,110 280,110 200,170 230,270
                   150,210 70,270 100,170 20,110 120,110"
           fill="#FDD835" stroke="#F57F17" stroke-width="3" />
</svg>

六边形

<svg width="300" height="260">
  <polygon points="150,10 265,80 265,190 150,260 35,190 35,80"
           fill="none" stroke="#4CAF50" stroke-width="4" />
</svg>

菱形

<svg width="300" height="200">
  <polygon points="150,20 260,100 150,180 40,100" fill="#3F51B5" />
</svg>

polygon 要点

  • points 用空格或逗号分隔坐标对
  • 图形自动闭合(首尾相连)
  • 支持 fill / stroke / opacity 等通用属性
💡 提示

想画不规则形状(气泡、对话框尾巴)时,polygon 比 path 更简单直接。

SVG 多段线

多段线(<polyline>)与 polygon 类似,但不自动闭合,常用于折线图、波形图。

基本多段线

<svg width="300" height="200">
  <polyline points="20,160 80,120 140,140 200,60 260,90 290,30"
            fill="none" stroke="#E91E63" stroke-width="3" />
</svg>

polyline vs polygon

对比项polylinepolygon
闭合不闭合自动闭合
填充效果不填(或填但缺闭合边)填充闭合区域
典型用途折线图、走势星形、多边形图标

折线图示例

<svg width="320" height="200">
  <!-- 网格线 -->
  <line x1="30" y1="170" x2="300" y2="170" stroke="#ccc"/>
  <line x1="30" y1="120" x2="300" y2="120" stroke="#eee"/>
  <line x1="30" y1="70" x2="300" y2="70" stroke="#eee"/>
  <!-- 数据折线 -->
  <polyline points="50,150 100,130 150,140 200,90 250,100 290,50"
            fill="none" stroke="#2196F3" stroke-width="3"/>
  <!-- 数据点 -->
  <circle cx="50" cy="150" r="4" fill="#2196F3"/>
  <circle cx="100" cy="130" r="4" fill="#2196F3"/>
  <circle cx="150" cy="140" r="4" fill="#2196F3"/>
  <circle cx="200" cy="90" r="4" fill="#2196F3"/>
  <circle cx="250" cy="100" r="4" fill="#2196F3"/>
  <circle cx="290" cy="50" r="4" fill="#2196F3"/>
</svg>
💡 提示

fill 设为 none 是 polyline 的常用做法;若想填充折线与底边围成的区域,可改用 polygon 并在末尾加回起点坐标。

SVG 路径

路径(<path>)是 SVG 最强大、最灵活的绘图元素,几乎所有复杂图形都能用它描述。

path 的命令

d 属性由命令字母 + 参数组成:

命令含义示例
M x y移动到某点(Move)M 10 10
L x y画直线到某点(Line)L 100 100
H x水平线H 150
V y垂直线V 150
C x1 y1 x2 y2 x y三次贝塞尔曲线C ...
Q x1 y1 x y二次贝塞尔曲线Q ...
A rx ry rot large sweep x y圆弧A 20 20 0 0 1 100 100
Z闭合路径Z

直线路径(三角形)

<svg width="300" height="200">
  <path d="M 150 20 L 250 180 L 50 180 Z"
        fill="#FF5722" stroke="#BF360C" stroke-width="3" />
</svg>

圆角矩形路径

<svg width="300" height="150">
  <path d="M 20 40 H 200 Q 220 40 220 60 V 110 Q 220 130 200 130 H 40
           Q 20 130 20 110 V 60 Q 20 40 40 40 Z"
        fill="#4CAF50" />
</svg>

贝塞尔曲线(爱心)

<svg width="300" height="260">
  <path d="M 150 230 C 60 170 30 110 60 60 C 85 20 135 30 150 80
           C 165 30 215 20 240 60 C 270 110 240 170 150 230 Z"
        fill="#E91E63" />
</svg>

圆弧(半圆)

<svg width="300" height="200">
  <path d="M 30 150 A 120 120 0 0 1 270 150" fill="none" stroke="#3F51B5" stroke-width="6"/>
</svg>

相对命令(小写)

小写命令基于当前点相对移动,更便于编写可平移的路径:

<!-- 等价于 M 50 50 L 150 50 L 100 150 Z -->
<path d="m 50 50 l 100 0 l -50 100 z" fill="teal"/>
💡 提示

复杂 path 通常由设计工具(Figma/Illustrator)导出,不必手写;理解命令能帮你读懂和微调导出的路径。

SVG 文本

文本(<text>)用于在 SVG 中绘制文字,支持丰富的排版属性。

基本文本

<svg width="300" height="100">
  <text x="20" y="60" font-size="28" fill="#333">Hello SVG</text>
</svg>

文本对齐

<svg width="300" height="120">
  <text x="150" y="40" text-anchor="start" font-size="20" fill="crimson">左对齐</text>
  <text x="150" y="70" text-anchor="middle" font-size="20" fill="navy">居中</text>
  <text x="150" y="100" text-anchor="end" font-size="20" fill="green">右对齐</text>
</svg>

字号与字体

<text x="20" y="40" font-family="Arial, sans-serif" font-size="24" font-weight="bold">加粗文字</text>
<text x="20" y="80" font-style="italic" font-size="20">斜体文字</text>

描边文字

<text x="20" y="70" font-size="40" font-weight="bold"
      fill="none" stroke="#FF9800" stroke-width="1.5">轮廓字</text>

多行文本

用多个 <tspan> 控制每行:

<svg width="300" height="150">
  <text x="20" y="40" font-size="18" fill="#333">
    <tspan x="20" dy="0">第一行文字</tspan>
    <tspan x="20" dy="28">第二行文字</tspan>
    <tspan x="20" dy="28" fill="#E91E63">第三行(红色)</tspan>
  </text>
</svg>

文字路径

让文字沿路径排列:

<svg width="400" height="200">
  <defs>
    <path id="curve" d="M 30 150 Q 200 30 370 150" fill="none"/>
  </defs>
  <text font-size="20" fill="#673AB7">
    <textPath href="#curve">文字沿着弧线排列显示</textPath>
  </text>
</svg>
💡 提示

text-anchor(对齐)配合 x=容器中点,可以实现水平居中;垂直居中可用 dominant-baseline="middle"。

SVG Stroke 属性

Stroke(描边)属性控制图形的轮廓:颜色、宽度、虚线、端点等。

基础描边

<svg width="300" height="120">
  <rect x="20" y="30" width="200" height="60" fill="none"
        stroke="#2196F3" stroke-width="4" />
</svg>

虚线描边

<svg width="300" height="200">
  <!-- dasharray:线段长,间隔 -->
  <line x1="20" y1="50" x2="280" y2="50" stroke="#333" stroke-width="4"
        stroke-dasharray="10 5" />
  <line x1="20" y1="100" x2="280" y2="100" stroke="#333" stroke-width="4"
        stroke-dasharray="20 5 5 5" />
  <line x1="20" y1="150" x2="280" y2="150" stroke="#E91E63" stroke-width="6"
        stroke-dasharray="15 8" stroke-linecap="round" />
</svg>

端点样式(linecap)

值效果
butt平头(默认)
round圆头
square方头(比 butt 略长)

连接点样式(linejoin)

<svg width="300" height="120">
  <path d="M 30 90 L 70 30 L 110 90" fill="none" stroke="#333" stroke-width="12" stroke-linejoin="miter"/>
  <path d="M 130 90 L 170 30 L 210 90" fill="none" stroke="#333" stroke-width="12" stroke-linejoin="round"/>
  <path d="M 230 90 L 270 30 L 310 90" fill="none" stroke="#333" stroke-width="12" stroke-linejoin="bevel"/>
</svg>

动画描边(进度条效果)

<svg width="300" height="100">
  <style>
    .progress { stroke-dasharray: 300; stroke-dashoffset: 300;
                animation: draw 2s forwards; }
    @keyframes draw { to { stroke-dashoffset: 60; } }
  </style>
  <rect x="10" y="40" width="280" height="20" rx="10" fill="#eee"/>
  <rect class="progress" x="10" y="40" width="280" height="20" rx="10"
        fill="none" stroke="#4CAF50" stroke-width="20"/>
</svg>
💡 提示

stroke-dashoffset 动画是绘制"描边动画"的经典技巧:先把线全部"藏起来",再动画显示到目标长度。

SVG 滤镜

滤镜(<filter>)可以给 SVG 图形添加模糊、阴影、发光、扭曲等效果,实现复杂的视觉表现。

滤镜的基本结构

<svg width="300" height="200">
  <defs>
    <filter id="myFilter">
      <!-- 这里放滤镜原语 -->
    </filter>
  </defs>
  <rect x="50" y="50" width="200" height="100" fill="#2196F3" filter="url(#myFilter)"/>
</svg>

常用滤镜原语

原语作用
feGaussianBlur高斯模糊
feDropShadow投影阴影
feOffset偏移
feFlood填充色块
feBlend混合
feColorMatrix颜色矩阵变换

高斯模糊

<svg width="300" height="150">
  <defs>
    <filter id="blur">
      <feGaussianBlur stdDeviation="3" />
    </filter>
  </defs>
  <rect x="50" y="40" width="200" height="80" fill="#FF9800" filter="url(#blur)"/>
</svg>

多滤镜叠加

<filter id="multi">
  <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
  <feOffset in="blur" dx="3" dy="3" result="shadow"/>
  <feMerge>
    <feMergeNode in="shadow"/>
    <feMergeNode in="SourceGraphic"/>
  </feMerge>
</filter>

这个滤镜实现了"投影 + 原图"的合成效果。

💡 提示

滤镜比较消耗性能,避免在大量元素上叠加复杂滤镜;能用 CSS 的 filter 属性(如 blur()、drop-shadow())时优先用 CSS。

SVG 模糊效果

给图形添加模糊效果,能模拟景深、毛玻璃,或作为发光底衬。

高斯模糊滤镜

<svg width="300" height="150">
  <defs>
    <filter id="gblur">
      <feGaussianBlur stdDeviation="5" />
    </filter>
  </defs>
  <rect x="40" y="40" width="220" height="80" rx="12" fill="#4CAF50" filter="url(#gblur)"/>
</svg>

stdDeviation 值越大模糊越明显。

模糊程度对比

<svg width="360" height="120">
  <defs>
    <filter id="b1"><feGaussianBlur stdDeviation="0"/></filter>
    <filter id="b2"><feGaussianBlur stdDeviation="3"/></filter>
    <filter id="b3"><feGaussianBlur stdDeviation="8"/></filter>
  </defs>
  <circle cx="60" cy="60" r="35" fill="#E91E63" filter="url(#b1)"/>
  <circle cx="180" cy="60" r="35" fill="#E91E63" filter="url(#b2)"/>
  <circle cx="300" cy="60" r="35" fill="#E91E63" filter="url(#b3)"/>
</svg>

CSS 模糊(替代方案)

<style>
  .blur-img { filter: blur(4px); }
</style>
<img class="blur-img" src="photo.jpg" width="300">

模糊发光效果

<svg width="200" height="200">
  <defs>
    <filter id="glow">
      <feGaussianBlur stdDeviation="6" result="blur"/>
      <feMerge>
        <feMergeNode in="blur"/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>
  <circle cx="100" cy="100" r="50" fill="#FFD700" filter="url(#glow)"/>
</svg>
💡 提示

发光效果 = 模糊副本 + 原图叠加,用 feMerge 把两者合成,是 SVG 常用技巧。

SVG 阴影

阴影让图形有立体感。SVG 有两种实现方式:滤镜 feDropShadow 或偏移 + 合成。

feDropShadow 阴影

<svg width="300" height="200">
  <defs>
    <filter id="drop">
      <feDropShadow dx="4" dy="4" stdDeviation="4" flood-color="#000" flood-opacity="0.4"/>
    </filter>
  </defs>
  <rect x="60" y="50" width="180" height="100" rx="10" fill="#fff" filter="url(#drop)"/>
</svg>

参数说明

属性作用
dx / dy阴影偏移距离
stdDeviation模糊程度
flood-color阴影颜色
flood-opacity阴影透明度

彩色阴影

<svg width="300" height="200">
  <defs>
    <filter id="colorShadow">
      <feDropShadow dx="3" dy="6" stdDeviation="5" flood-color="#9C27B0" flood-opacity="0.6"/>
    </filter>
  </defs>
  <circle cx="150" cy="100" r="60" fill="#4CAF50" filter="url(#colorShadow)"/>
</svg>

传统方式(偏移+合成)

<filter id="oldShadow">
  <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
  <feOffset in="blur" dx="3" dy="3" result="off"/>
  <feMerge>
    <feMergeNode in="off"/>
    <feMergeNode in="SourceGraphic"/>
  </feMerge>
</filter>

CSS 阴影(替代方案)

.card {
  filter: drop-shadow(4px 4px 6px rgba(0,0,0,0.3));
}
💡 提示

给内联 SVG 加阴影,CSS 的 filter: drop-shadow() 最简单;复杂多色阴影再用 SVG 滤镜。

SVG 渐变 - 线性

线性渐变让颜色沿直线方向平滑过渡,是 SVG 最常见的渐变方式。

定义线性渐变

<svg width="300" height="150">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" stop-color="#FF512F" />
      <stop offset="100%" stop-color="#DD2476" />
    </linearGradient>
  </defs>
  <rect x="30" y="30" width="240" height="90" rx="8" fill="url(#grad1)" />
</svg>

渐变方向

<!-- 水平(默认) -->
<linearGradient id="gH" x1="0%" y1="0%" x2="100%" y2="0%">...</linearGradient>
<!-- 垂直 -->
<linearGradient id="gV" x1="0%" y1="0%" x2="0%" y2="100%">...</linearGradient>
<!-- 对角 -->
<linearGradient id="gD" x1="0%" y1="0%" x2="100%" y2="100%">...</linearGradient>

多色渐变

<linearGradient id="rainbow" x1="0%" y1="0%" x2="100%" y2="0%">
  <stop offset="0%" stop-color="#f00"/>
  <stop offset="33%" stop-color="#0f0"/>
  <stop offset="66%" stop-color="#00f"/>
  <stop offset="100%" stop-color="#f0f"/>
</linearGradient>

描边渐变

<svg width="300" height="150">
  <defs>
    <linearGradient id="strokeGrad" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" stop-color="#1FA2FF"/>
      <stop offset="100%" stop-color="#12D8FA"/>
    </linearGradient>
  </defs>
  <rect x="30" y="40" width="240" height="80" rx="12"
        fill="none" stroke="url(#strokeGrad)" stroke-width="6"/>
</svg>

渐变 vs 纯色

对比项纯色 fill渐变 fill
视觉扁平有层次
性能更快略慢
适用简洁 UI按钮、Logo、图表
💡 提示

渐变定义放在 <defs> 中,通过 fill="url(#id)" 引用,可被多个元素复用。

SVG 渐变- 放射性

放射性渐变从中心点向外扩散颜色,适合做光晕、球体、按钮高光。

基本径向渐变

<svg width="200" height="200">
  <defs>
    <radialGradient id="rad">
      <stop offset="0%" stop-color="#fff" />
      <stop offset="100%" stop-color="#FF5722" />
    </radialGradient>
  </defs>
  <circle cx="100" cy="100" r="80" fill="url(#rad)" />
</svg>

控制中心与半径

<radialGradient id="rad2" cx="30%" cy="30%" r="70%">
  <stop offset="0%" stop-color="#FFEB3B"/>
  <stop offset="100%" stop-color="#F57C00"/>
</radialGradient>

cx / cy 控制渐变中心(相对元素),r 控制扩散半径。

球体效果

<svg width="200" height="200">
  <defs>
    <radialGradient id="ball" cx="35%" cy="30%" r="75%">
      <stop offset="0%" stop-color="#B3E5FC"/>
      <stop offset="45%" stop-color="#2196F3"/>
      <stop offset="100%" stop-color="#0D47A1"/>
    </radialGradient>
  </defs>
  <circle cx="100" cy="100" r="80" fill="url(#ball)"/>
</svg>

多重 stop

<radialGradient id="multi">
  <stop offset="0%" stop-color="#fff"/>
  <stop offset="40%" stop-color="#FFC107"/>
  <stop offset="100%" stop-color="#E65100"/>
</radialGradient>

线性 vs 径向

对比项linearGradientradialGradient
扩散方向沿直线由中心向外
关键属性x1 y1 x2 y2cx cy r
典型效果按钮渐变、横幅球体、光晕、高光
💡 提示

中心点(cx cy)偏离几何中心(如 35%, 30%)能模拟"光源在斜上方"的效果,让球体更真实。

SVG 实例

综合运用所学,绘制一个完整实例:带渐变、阴影、文字和动画的 SVG 图标。

实例:仪表盘卡片

<svg width="300" height="220" viewBox="0 0 300 220">
  <defs>
    <linearGradient id="cardBg" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" stop-color="#667eea"/>
      <stop offset="100%" stop-color="#764ba2"/>
    </linearGradient>
    <filter id="shadow">
      <feDropShadow dx="2" dy="4" stdDeviation="6" flood-opacity="0.3"/>
    </filter>
  </defs>

  <!-- 卡片背景 -->
  <rect x="30" y="30" width="240" height="160" rx="16" fill="url(#cardBg)" filter="url(#shadow)"/>

  <!-- 进度环 -->
  <circle cx="100" cy="110" r="45" fill="none" stroke="rgba(255,255,255,0.2)" stroke-width="10"/>
  <circle cx="100" cy="110" r="45" fill="none" stroke="#fff" stroke-width="10"
          stroke-linecap="round" stroke-dasharray="283" stroke-dashoffset="85"
          transform="rotate(-90 100 110)"/>
  <text x="100" y="118" text-anchor="middle" font-size="22" fill="#fff" font-weight="bold">70%</text>

  <!-- 文字 -->
  <text x="190" y="95" text-anchor="middle" font-size="16" fill="rgba(255,255,255,0.85)">完成率</text>
  <text x="190" y="120" text-anchor="middle" font-size="20" fill="#fff" font-weight="bold">目标 100</text>
</svg>

实例解析

元素作用
linearGradient卡片渐变背景
feDropShadow卡片投影
circle × 2进度环(底环 + 进度弧)
stroke-dasharray弧长 283(周长),进度偏移 85 = 70%
rotate(-90 ...)让进度从 12 点方向开始
text × 3百分比与说明文字

进度环原理

圆的周长 2πr = 2 × 3.14 × 45 ≈ 283。设置 stroke-dasharray="283" 后,用 stroke-dashoffset 隐藏一部分即可显示进度:70% 进度 = 283 × (1 - 0.7) ≈ 85。

💡 提示

用 JS 动态修改 stroke-dashoffset,就能做出丝滑的进度动画,这是很多仪表盘的实现方式。

SVG 参考手册

本节提供 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
<path>任意路径d
<text>文本x y font-size text-anchor
<g>分组—(可整体变换/样式)
<defs>定义复用资源渐变/滤镜/符号
<use>复用已定义元素href

通用样式属性

属性说明
fill填充色(none 表示不填充)
fill-opacity填充透明度 0-1
stroke描边色
stroke-width描边宽度
stroke-dasharray虚线(线段长,间隔)
stroke-linecap端点样式 butt/round/square
stroke-linejoin连接样式 miter/round/bevel
opacity整体透明度
transform变换

常用变换

transform="translate(x, y)"   <!-- 平移 -->
transform="rotate(45)"        <!-- 旋转(可带中心点 rotate(45 cx cy))-->
transform="scale(2)"          <!-- 缩放 -->
transform="skewX(20)"         <!-- 斜切 -->

viewBox 示例

<!-- viewBox: minX minY width height -->
<svg viewBox="0 0 100 100" width="200" height="200">
  <rect x="25" y="25" width="50" height="50" fill="teal"/>
</svg>
💡 提示

完整规范可查阅 MDN SVG 文档(developer.mozilla.org),它是最权威的参考手册。

在线实例

本节整理一批在线 SVG 工具,帮助你在不写代码的情况下快速制作和调试 SVG。

可视化设计工具

工具用途
Figma专业 UI/矢量设计,可导出 SVG
Illustrator专业矢量绘图
draw.io免费流程图/架构图,导出 SVG
Inkscape免费开源矢量编辑器

图标库

图标库说明
Font Awesome经典图标库
Material IconsGoogle 风格图标
Tabler Icons开源免费 SVG 图标
Lucide轻量开源图标(Vue/React 友好)

在线工具

  • yqnn.github.io/svg-path-editor:path 可视化编辑器
  • svgoptimizer.com:SVG 压缩优化
  • caniuse.com:浏览器兼容性查询
  • SVGOMG:SVG 优化(svgomg.netlify.app)

实战建议

  1. 简单图标:从图标库复制 SVG 代码直接使用
  2. 自定义图形:Figma/draw.io 画好后导出
  3. 动画:用 CSS 或 SMIL 在内联 SVG 上实现
  4. 优化:上线前用 SVGOMG 压缩体积
💡 提示

下载的图标 SVG 常含冗余代码,用 SVGOMG 优化后再引入项目,可显著减小体积。

第 1 / 22 节