Skip to content

SVG (Scalable Vector Graphics) ​

什么是SVG ​

SVG是一种基于XML的矢量图形格式,用于描述二维图形和图形应用程序。与栅格图像(如JPEG、PNG)不同,SVG图像是由数学公式定义的,因此可以无限缩放而不会失去质量。

基本结构 ​

svg
<svg version="1.1"
     baseProfile="full"
     width="300" height="200"
     xmlns="http://www.w3.org/2000/svg">
  <!-- 图形内容 -->
</svg>
<svg version="1.1"
     baseProfile="full"
     width="300" height="200"
     xmlns="http://www.w3.org/2000/svg">
  <!-- 图形内容 -->
</svg>

根元素属性 ​

  • width 和 height:设置SVG画布的尺寸
  • viewBox:定义SVG的坐标系和可见区域
    svg
    <svg viewBox="0 0 300 200" width="300" height="200">
    <svg viewBox="0 0 300 200" width="300" height="200">
  • xmlns:指定SVG命名空间,必须为http://www.w3.org/2000/svg

基本形状 ​

矩形 (rect) ​

svg
<rect x="50" y="50" width="200" height="100" 
      fill="blue" stroke="red" stroke-width="2" 
      rx="10" ry="10" />
<rect x="50" y="50" width="200" height="100" 
      fill="blue" stroke="red" stroke-width="2" 
      rx="10" ry="10" />
  • x, y:矩形左上角坐标
  • width, height:矩形尺寸
  • rx, ry:圆角半径

圆形 (circle) ​

svg
<circle cx="150" cy="100" r="80" 
        fill="green" stroke="black" stroke-width="3" />
<circle cx="150" cy="100" r="80" 
        fill="green" stroke="black" stroke-width="3" />
  • cx, cy:圆心坐标
  • r:半径

椭圆 (ellipse) ​

svg
<ellipse cx="150" cy="100" rx="100" ry="50" 
         fill="purple" stroke="yellow" stroke-width="2" />
<ellipse cx="150" cy="100" rx="100" ry="50" 
         fill="purple" stroke="yellow" stroke-width="2" />
  • cx, cy:椭圆中心坐标
  • rx:水平半径
  • ry:垂直半径

线 (line) ​

svg
<line x1="50" y1="50" x2="250" y2="150" 
      stroke="red" stroke-width="3" />
<line x1="50" y1="50" x2="250" y2="150" 
      stroke="red" stroke-width="3" />
  • x1, y1:起点坐标
  • x2, y2:终点坐标

折线 (polyline) ​

svg
<polyline points="50,100 100,50 150,100 200,50 250,100" 
          fill="none" stroke="blue" stroke-width="3" />
<polyline points="50,100 100,50 150,100 200,50 250,100" 
          fill="none" stroke="blue" stroke-width="3" />
  • points:折线顶点坐标列表,格式为x1,y1 x2,y2 x3,y3...

多边形 (polygon) ​

svg
<polygon points="150,50 250,150 50,150" 
         fill="orange" stroke="black" stroke-width="2" />
<polygon points="150,50 250,150 50,150" 
         fill="orange" stroke="black" stroke-width="2" />
  • points:多边形顶点坐标列表,格式为x1,y1 x2,y2 x3,y3...
  • 自动闭合路径

路径 (path) ​

路径是最强大的SVG元素,可用于创建任何形状。

svg
<path d="M150 50 L250 150 L50 150 Z" 
      fill="pink" stroke="red" stroke-width="2" />
<path d="M150 50 L250 150 L50 150 Z" 
      fill="pink" stroke="red" stroke-width="2" />
  • d:路径数据,包含以下命令:
    • M:移动到 (Move to)
    • L:直线到 (Line to)
    • H:水平直线到 (Horizontal line to)
    • V:垂直直线到 (Vertical line to)
    • C:三次贝塞尔曲线 (Cubic Bezier curve)
    • S:平滑三次贝塞尔曲线 (Smooth cubic Bezier curve)
    • Q:二次贝塞尔曲线 (Quadratic Bezier curve)
    • T:平滑二次贝塞尔曲线 (Smooth quadratic Bezier curve)
    • A:椭圆弧 (Elliptical arc)
    • Z:闭合路径 (Close path)

SVG样式 ​

内联样式 ​

svg
<rect x="50" y="50" width="200" height="100" 
      style="fill: blue; stroke: red; stroke-width: 2; rx: 10; ry: 10;" />
<rect x="50" y="50" width="200" height="100" 
      style="fill: blue; stroke: red; stroke-width: 2; rx: 10; ry: 10;" />

CSS样式 ​

svg
<svg>
  <style>
    .my-rect {
      fill: blue;
      stroke: red;
      stroke-width: 2;
      rx: 10;
      ry: 10;
    }
  </style>
  <rect x="50" y="50" width="200" height="100" class="my-rect" />
</svg>
<svg>
  <style>
    .my-rect {
      fill: blue;
      stroke: red;
      stroke-width: 2;
      rx: 10;
      ry: 10;
    }
  </style>
  <rect x="50" y="50" width="200" height="100" class="my-rect" />
</svg>

外部CSS ​

html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <svg>
    <rect x="50" y="50" width="200" height="100" class="my-rect" />
  </svg>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <svg>
    <rect x="50" y="50" width="200" height="100" class="my-rect" />
  </svg>
</body>
</html>

SVG变换 ​

平移 (translate) ​

svg
<rect x="50" y="50" width="100" height="100" fill="blue" 
      transform="translate(50, 50)" />
<rect x="50" y="50" width="100" height="100" fill="blue" 
      transform="translate(50, 50)" />

旋转 (rotate) ​

svg
<rect x="100" y="100" width="100" height="100" fill="red" 
      transform="rotate(45)" />
<rect x="100" y="100" width="100" height="100" fill="red" 
      transform="rotate(45)" />

缩放 (scale) ​

svg
<rect x="100" y="100" width="100" height="100" fill="green" 
      transform="scale(0.5)" />
<rect x="100" y="100" width="100" height="100" fill="green" 
      transform="scale(0.5)" />

倾斜 (skew) ​

svg
<rect x="100" y="100" width="100" height="100" fill="purple" 
      transform="skewX(30)" />
<rect x="100" y="100" width="100" height="100" fill="purple" 
      transform="skewX(30)" />

复合变换 ​

svg
<rect x="100" y="100" width="100" height="100" fill="orange" 
      transform="translate(50, 50) rotate(45) scale(0.5)" />
<rect x="100" y="100" width="100" height="100" fill="orange" 
      transform="translate(50, 50) rotate(45) scale(0.5)" />

SVG动画 ​

SMIL动画 ​

svg
<rect x="50" y="50" width="100" height="100" fill="blue">
  <animate attributeName="width" from="100" to="200" dur="2s" repeatCount="indefinite" />
  <animate attributeName="height" from="100" to="150" dur="2s" repeatCount="indefinite" />
  <animate attributeName="fill" from="blue" to="red" dur="2s" repeatCount="indefinite" />
</rect>
<rect x="50" y="50" width="100" height="100" fill="blue">
  <animate attributeName="width" from="100" to="200" dur="2s" repeatCount="indefinite" />
  <animate attributeName="height" from="100" to="150" dur="2s" repeatCount="indefinite" />
  <animate attributeName="fill" from="blue" to="red" dur="2s" repeatCount="indefinite" />
</rect>

CSS动画 ​

svg
<svg>
  <style>
    @keyframes pulse {
      0% { transform: scale(1); fill: blue; }
      50% { transform: scale(1.2); fill: red; }
      100% { transform: scale(1); fill: blue; }
    }
    .animated-rect {
      animation: pulse 2s infinite;
    }
  </style>
  <rect x="100" y="100" width="100" height="100" class="animated-rect" />
</svg>
<svg>
  <style>
    @keyframes pulse {
      0% { transform: scale(1); fill: blue; }
      50% { transform: scale(1.2); fill: red; }
      100% { transform: scale(1); fill: blue; }
    }
    .animated-rect {
      animation: pulse 2s infinite;
    }
  </style>
  <rect x="100" y="100" width="100" height="100" class="animated-rect" />
</svg>

SVG滤镜 ​

高斯模糊 (Gaussian Blur) ​

svg
<defs>
  <filter id="blur">
    <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
  </filter>
</defs>
<rect x="100" y="100" width="100" height="100" fill="blue" filter="url(#blur)" />
<defs>
  <filter id="blur">
    <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
  </filter>
</defs>
<rect x="100" y="100" width="100" height="100" fill="blue" filter="url(#blur)" />

阴影 (Drop Shadow) ​

svg
<defs>
  <filter id="shadow">
    <feDropShadow dx="5" dy="5" stdDeviation="3" flood-color="black" flood-opacity="0.5" />
  </filter>
</defs>
<rect x="100" y="100" width="100" height="100" fill="red" filter="url(#shadow)" />
<defs>
  <filter id="shadow">
    <feDropShadow dx="5" dy="5" stdDeviation="3" flood-color="black" flood-opacity="0.5" />
  </filter>
</defs>
<rect x="100" y="100" width="100" height="100" fill="red" filter="url(#shadow)" />

SVG文本 ​

基本文本 ​

svg
<text x="150" y="100" font-size="24" fill="blue" text-anchor="middle">Hello SVG!</text>
<text x="150" y="100" font-size="24" fill="blue" text-anchor="middle">Hello SVG!</text>

多行文本 ​

svg
<text x="150" y="100" font-size="24" fill="green" text-anchor="middle">
  <tspan x="150" dy="0">第一行文本</tspan>
  <tspan x="150" dy="30">第二行文本</tspan>
  <tspan x="150" dy="30">第三行文本</tspan>
</text>
<text x="150" y="100" font-size="24" fill="green" text-anchor="middle">
  <tspan x="150" dy="0">第一行文本</tspan>
  <tspan x="150" dy="30">第二行文本</tspan>
  <tspan x="150" dy="30">第三行文本</tspan>
</text>

文本路径 ​

svg
<defs>
  <path id="curve" d="M50,150 Q150,50 250,150" fill="none" stroke="transparent" />
</defs>
<text font-size="24" fill="purple">
  <textPath href="#curve">文本沿曲线排列</textPath>
</text>
<defs>
  <path id="curve" d="M50,150 Q150,50 250,150" fill="none" stroke="transparent" />
</defs>
<text font-size="24" fill="purple">
  <textPath href="#curve">文本沿曲线排列</textPath>
</text>

SVG渐变 ​

线性渐变 ​

svg
<defs>
  <linearGradient id="linear-gradient" 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="green" />
  </linearGradient>
</defs>
<rect x="100" y="100" width="200" height="100" fill="url(#linear-gradient)" />
<defs>
  <linearGradient id="linear-gradient" 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="green" />
  </linearGradient>
</defs>
<rect x="100" y="100" width="200" height="100" fill="url(#linear-gradient)" />

径向渐变 ​

svg
<defs>
  <radialGradient id="radial-gradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
    <stop offset="0%" stop-color="white" />
    <stop offset="100%" stop-color="blue" />
  </radialGradient>
</defs>
<circle cx="150" cy="150" r="100" fill="url(#radial-gradient)" />
<defs>
  <radialGradient id="radial-gradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
    <stop offset="0%" stop-color="white" />
    <stop offset="100%" stop-color="blue" />
  </radialGradient>
</defs>
<circle cx="150" cy="150" r="100" fill="url(#radial-gradient)" />

SVG与JavaScript ​

html
<!DOCTYPE html>
<html>
<body>
  <svg id="my-svg" width="300" height="200">
    <rect id="my-rect" x="50" y="50" width="100" height="100" fill="blue" />
  </svg>
  
  <script>
    // 获取SVG元素
    const svg = document.getElementById('my-svg');
    const rect = document.getElementById('my-rect');
    
    // 改变属性
    rect.setAttribute('fill', 'red');
    rect.setAttribute('width', '150');
    
    // 添加事件监听
    rect.addEventListener('click', function() {
      this.setAttribute('fill', this.getAttribute('fill') === 'red' ? 'blue' : 'red');
    });
    
    // 创建新元素
    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    circle.setAttribute('cx', '200');
    circle.setAttribute('cy', '100');
    circle.setAttribute('r', '50');
    circle.setAttribute('fill', 'green');
    svg.appendChild(circle);
  </script>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
  <svg id="my-svg" width="300" height="200">
    <rect id="my-rect" x="50" y="50" width="100" height="100" fill="blue" />
  </svg>
  
  <script>
    // 获取SVG元素
    const svg = document.getElementById('my-svg');
    const rect = document.getElementById('my-rect');
    
    // 改变属性
    rect.setAttribute('fill', 'red');
    rect.setAttribute('width', '150');
    
    // 添加事件监听
    rect.addEventListener('click', function() {
      this.setAttribute('fill', this.getAttribute('fill') === 'red' ? 'blue' : 'red');
    });
    
    // 创建新元素
    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
    circle.setAttribute('cx', '200');
    circle.setAttribute('cy', '100');
    circle.setAttribute('r', '50');
    circle.setAttribute('fill', 'green');
    svg.appendChild(circle);
  </script>
</body>
</html>

SVG最佳实践 ​

  1. 使用合适的形状:根据需求选择最合适的SVG元素,简单形状使用基本元素,复杂形状使用路径
  2. 优化路径:减少路径点数,使用更简单的命令
  3. 使用CSS样式:将样式与结构分离,便于维护和修改
  4. 使用 viewBox:确保SVG可缩放,适应不同尺寸
  5. 压缩SVG:使用工具如SVGO压缩SVG文件大小
  6. 使用defs和use:复用图形元素,减少代码冗余
  7. 考虑可访问性:添加适当的title和desc元素,确保屏幕阅读器可以理解
  8. 测试跨浏览器兼容性:不同浏览器对SVG的支持可能有所不同

SVG优化工具 ​

  • SVGO:一个Node.js工具,用于压缩SVG文件
  • Inkscape:一个开源的矢量图形编辑器,可用于创建和优化SVG
  • Adobe Illustrator:专业的矢量图形编辑器,支持导出优化的SVG
  • SVGOMG:SVGO的在线版本,提供可视化的优化选项

SVG应用场景 ​

  1. 图标:网站和应用程序的图标
  2. Logo:品牌标识,可无损缩放
  3. 数据可视化:图表、图形和仪表盘
  4. 动画:网页和应用程序中的动画效果
  5. 交互元素:可交互的图形和控件
  6. 地图:交互式地图和地理数据可视化
  7. 游戏图形:2D游戏中的图形元素

浏览器支持 ​

SVG在所有现代浏览器中都得到了良好的支持,包括:

  • Chrome 4+
  • Firefox 3.5+
  • Safari 3.1+
  • Edge 12+
  • Internet Explorer 9+

对于旧版浏览器,可以使用SVG的替代方案,如Canvas或服务器端渲染的图片。