Skip to content

8.1 SVG基础

关键词: SVG矢量图形, 可缩放矢量图形, SVG语法, HTML内联SVG, 矢量图形优势, SVG与Canvas, SVG基础元素, 图形标记

学习目标

  • 理解SVG的基本概念和优势特点
  • 掌握SVG与Canvas的区别和应用场景
  • 学会SVG在HTML中的基本语法和使用方法
  • 理解SVG矢量图形的基本原理和特征
  • 掌握SVG元素的基本属性和配置方法

8.1.1 SVG简介和优势

SVG的基本概念

SVG(Scalable Vector Graphics)是一种基于XML的矢量图形格式,是HTML5的重要组成部分。SVG使用数学描述来定义图形,而不是像素点。

html
<!-- 最简单的SVG元素 -->
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
    <circle cx="100" cy="100" r="50" fill="blue" />
</svg>

SVG的主要优势

SVG矢量图形具有以下重要优势:

html
<!-- 可缩放性示例 -->
<div class="svg-scalability-demo">
    <h4>SVG可缩放性演示</h4>
    <svg width="100" height="100" viewBox="0 0 100 100">
        <rect x="10" y="10" width="80" height="80" fill="red" />
        <text x="50" y="50" text-anchor="middle" dy="0.35em">小尺寸</text>
    </svg>
    
    <svg width="200" height="200" viewBox="0 0 100 100">
        <rect x="10" y="10" width="80" height="80" fill="red" />
        <text x="50" y="50" text-anchor="middle" dy="0.35em">大尺寸</text>
    </svg>
</div>

SVG的技术特点

html
<!-- SVG技术特点展示 -->
<div class="svg-features">
    <h4>SVG技术特点</h4>
    <svg width="400" height="300" viewBox="0 0 400 300">
        <!-- 矢量图形 -->
        <g id="vector-demo">
            <rect x="10" y="10" width="100" height="60" fill="lightblue" stroke="blue" stroke-width="2" />
            <text x="60" y="45" text-anchor="middle">矢量图形</text>
        </g>
        
        <!-- 可编辑文本 -->
        <g id="text-demo">
            <text x="150" y="40" font-size="16" fill="green">可编辑文本</text>
        </g>
        
        <!-- 可交互性 -->
        <g id="interactive-demo">
            <circle cx="300" cy="40" r="30" fill="orange" />
            <text x="300" y="45" text-anchor="middle" fill="white">交互</text>
        </g>
    </svg>
</div>

8.1.2 SVG与Canvas区别

技术对比

SVG和Canvas在技术特点上有明显区别:

html
<!-- SVG与Canvas对比展示 -->
<div class="svg-canvas-comparison">
    <h4>SVG与Canvas技术对比</h4>
    <div class="comparison-container">
        <div class="svg-example">
            <h5>SVG示例</h5>
            <svg width="200" height="150" viewBox="0 0 200 150">
                <rect x="20" y="20" width="160" height="110" fill="lightgreen" stroke="green" stroke-width="3" />
                <text x="100" y="80" text-anchor="middle" font-size="14">SVG矢量图形</text>
            </svg>
            <p>特点:可缩放、可编辑、DOM结构</p>
        </div>
        
        <div class="canvas-example">
            <h5>Canvas示例</h5>
            <canvas id="canvasExample" width="200" height="150">
                <p>Canvas位图图形</p>
                <p>特点:像素绘制、高性能、脚本驱动</p>
            </canvas>
        </div>
    </div>
</div>

应用场景对比

html
<!-- 应用场景对比 -->
<div class="usage-scenarios">
    <h4>应用场景对比</h4>
    <div class="scenarios-grid">
        <div class="svg-scenarios">
            <h5>SVG适用场景</h5>
            <svg width="150" height="100" viewBox="0 0 150 100">
                <rect x="10" y="10" width="130" height="80" fill="none" stroke="blue" stroke-width="2" />
                <text x="75" y="30" text-anchor="middle" font-size="12">图标设计</text>
                <text x="75" y="50" text-anchor="middle" font-size="12">Logo制作</text>
                <text x="75" y="70" text-anchor="middle" font-size="12">简单图表</text>
            </svg>
        </div>
        
        <div class="canvas-scenarios">
            <h5>Canvas适用场景</h5>
            <div class="canvas-scenario-box">
                <p>游戏开发</p>
                <p>复杂动画</p>
                <p>图像处理</p>
            </div>
        </div>
    </div>
</div>

8.1.3 SVG语法基础

SVG基本语法结构

SVG遵循XML语法规范,具有严格的结构要求:

html
<!-- SVG基本语法结构 -->
<svg width="300" height="200" 
     viewBox="0 0 300 200" 
     xmlns="http://www.w3.org/2000/svg">
    
    <!-- SVG内容 -->
    <rect x="10" y="10" width="100" height="80" fill="blue" />
    <circle cx="200" cy="50" r="40" fill="red" />
    <text x="150" y="150" text-anchor="middle" font-size="16">SVG文本</text>
</svg>

SVG命名空间

SVG使用XML命名空间来定义元素:

html
<!-- 完整的SVG命名空间声明 -->
<svg width="250" height="180" 
     viewBox="0 0 250 180"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
    
    <defs>
        <linearGradient id="myGradient" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
            <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
        </linearGradient>
    </defs>
    
    <rect x="10" y="10" width="230" height="160" fill="url(#myGradient)" />
</svg>

SVG属性语法

SVG属性遵循XML属性语法规范:

html
<!-- SVG属性语法示例 -->
<svg width="280" height="200" viewBox="0 0 280 200">
    <!-- 基本属性 -->
    <rect x="20" y="20" width="80" height="60" 
          fill="lightblue" 
          stroke="blue" 
          stroke-width="2" />
    
    <!-- 样式属性 -->
    <circle cx="180" cy="50" r="30" 
            style="fill:orange; stroke:red; stroke-width:3;" />
    
    <!-- 变换属性 -->
    <rect x="120" y="120" width="40" height="40" 
          fill="green" 
          transform="rotate(45 140 140)" />
</svg>

8.1.4 SVG在HTML中的使用

内联SVG

最常见的SVG使用方式是直接嵌入HTML文档中:

html
<!-- 内联SVG示例 -->
<article class="svg-inline-demo">
    <h4>内联SVG示例</h4>
    <p>以下是一个内联SVG图形:</p>
    <svg width="200" height="100" viewBox="0 0 200 100">
        <rect x="10" y="10" width="180" height="80" 
              fill="lavender" stroke="purple" stroke-width="2" />
        <text x="100" y="55" text-anchor="middle" 
              font-family="Arial" font-size="14" fill="darkblue">
            内联SVG
        </text>
    </svg>
    <p>SVG图形完美集成在HTML文档中。</p>
</article>

SVG作为图像

SVG可以像普通图像一样使用:

html
<!-- SVG作为图像使用 -->
<div class="svg-as-image">
    <h4>SVG作为图像使用</h4>
    
    <!-- 使用img标签 -->
    <div class="image-example">
        <h5>使用img标签</h5>
        <img src="example.svg" alt="SVG示例图像" width="150" height="100" />
    </div>
    
    <!-- 使用object标签 -->
    <div class="object-example">
        <h5>使用object标签</h5>
        <object data="example.svg" type="image/svg+xml" width="150" height="100">
            <p>您的浏览器不支持SVG</p>
        </object>
    </div>
    
    <!-- 使用embed标签 -->
    <div class="embed-example">
        <h5>使用embed标签</h5>
        <embed src="example.svg" type="image/svg+xml" width="150" height="100" />
    </div>
</div>

SVG背景图像

SVG也可以用作CSS背景图像:

html
<!-- SVG背景图像 -->
<div class="svg-background-demo">
    <h4>SVG背景图像</h4>
    <div class="bg-svg-box" style="
        width: 200px; 
        height: 150px; 
        background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE1MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjE1MCIgZmlsbD0iI2Y0ZjRmNCIvPgogIDxjaXJjbGUgY3g9IjEwMCIgY3k9Ijc1IiByPSI1MCIgZmlsbD0iI2RkZCIvPgo8L3N2Zz4=');
        background-size: cover;
        border: 2px solid #ccc;
    ">
        <p style="text-align: center; line-height: 150px; margin: 0;">SVG背景</p>
    </div>
</div>

8.1.5 SVG坐标系统和视口

SVG坐标系统

SVG使用自己的坐标系统,与Canvas类似但更加灵活:

html
<!-- SVG坐标系统演示 -->
<div class="svg-coordinate-system">
    <h4>SVG坐标系统</h4>
    <svg width="300" height="200" viewBox="0 0 300 200">
        <!-- 坐标系统网格 -->
        <defs>
            <pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
                <path d="M 20 0 L 0 0 0 20" fill="none" stroke="#ddd" stroke-width="1"/>
            </pattern>
        </defs>
        
        <rect width="300" height="200" fill="url(#grid)" />
        
        <!-- 坐标轴 -->
        <line x1="0" y1="0" x2="300" y2="0" stroke="red" stroke-width="2" />
        <line x1="0" y1="0" x2="0" y2="200" stroke="red" stroke-width="2" />
        
        <!-- 坐标点标记 -->
        <circle cx="0" cy="0" r="3" fill="red" />
        <text x="5" y="15" font-size="12" fill="red">原点(0,0)</text>
        
        <circle cx="100" cy="50" r="3" fill="blue" />
        <text x="105" y="45" font-size="12" fill="blue">(100,50)</text>
        
        <circle cx="200" cy="100" r="3" fill="green" />
        <text x="205" y="95" font-size="12" fill="green">(200,100)</text>
    </svg>
</div>

viewBox属性

viewBox是SVG中的重要概念,用于定义SVG的可视区域:

html
<!-- viewBox属性演示 -->
<div class="viewbox-demo">
    <h4>viewBox属性演示</h4>
    <div class="viewbox-examples">
        <div class="viewbox-example">
            <h5>原始尺寸</h5>
            <svg width="150" height="100" viewBox="0 0 150 100">
                <rect x="10" y="10" width="130" height="80" fill="lightcoral" stroke="darkred" stroke-width="2" />
                <text x="75" y="55" text-anchor="middle" font-size="12">viewBox="0 0 150 100"</text>
            </svg>
        </div>
        
        <div class="viewbox-example">
            <h5>缩放视图</h5>
            <svg width="150" height="100" viewBox="0 0 75 50">
                <rect x="10" y="10" width="130" height="80" fill="lightgreen" stroke="darkgreen" stroke-width="2" />
                <text x="75" y="55" text-anchor="middle" font-size="12">viewBox="0 0 75 50"</text>
            </svg>
        </div>
        
        <div class="viewbox-example">
            <h5>裁剪视图</h5>
            <svg width="150" height="100" viewBox="25 25 100 50">
                <rect x="10" y="10" width="130" height="80" fill="lightblue" stroke="darkblue" stroke-width="2" />
                <text x="75" y="55" text-anchor="middle" font-size="12">viewBox="25 25 100 50"</text>
            </svg>
        </div>
    </div>
</div>

8.1.6 SVG基础元素结构

SVG容器元素

SVG提供了多种容器元素来组织图形内容:

html
<!-- SVG容器元素 -->
<svg width="350" height="250" viewBox="0 0 350 250">
    <!-- 分组元素 -->
    <g id="shapes-group" transform="translate(10,10)">
        <rect x="0" y="0" width="80" height="60" fill="yellow" />
        <circle cx="40" cy="30" r="20" fill="orange" />
        <text x="40" y="35" text-anchor="middle" font-size="10">分组</text>
    </g>
    
    <!-- 定义元素 -->
    <defs>
        <linearGradient id="blueGradient" x1="0%" y1="0%" x2="100%" y2="100%">
            <stop offset="0%" style="stop-color:lightblue;stop-opacity:1" />
            <stop offset="100%" style="stop-color:darkblue;stop-opacity:1" />
        </linearGradient>
    </defs>
    
    <!-- 使用定义的渐变 -->
    <rect x="120" y="10" width="80" height="60" fill="url(#blueGradient)" />
    <text x="160" y="45" text-anchor="middle" font-size="12" fill="white">渐变</text>
    
    <!-- 符号元素 -->
    <symbol id="star" viewBox="0 0 20 20">
        <polygon points="10,1 13,7 19,7 14,12 16,18 10,15 4,18 6,12 1,7 7,7" fill="gold" />
    </symbol>
    
    <!-- 使用符号 -->
    <use href="#star" x="230" y="10" width="30" height="30" />
    <text x="245" y="55" text-anchor="middle" font-size="12">符号</text>
</svg>

SVG文档结构

完整的SVG文档具有清晰的结构:

html
<!-- 完整的SVG文档结构 -->
<svg width="400" height="300" 
     viewBox="0 0 400 300" 
     xmlns="http://www.w3.org/2000/svg"
     role="img" 
     aria-labelledby="svg-title" 
     aria-describedby="svg-desc">
    
    <!-- 标题和描述 -->
    <title id="svg-title">SVG文档结构示例</title>
    <desc id="svg-desc">这是一个展示SVG文档结构的示例图形</desc>
    
    <!-- 定义部分 -->
    <defs>
        <style>
            .header-text { font-size: 18px; font-weight: bold; fill: #333; }
            .content-text { font-size: 14px; fill: #666; }
        </style>
    </defs>
    
    <!-- 主要内容 -->
    <rect x="10" y="10" width="380" height="280" fill="none" stroke="#999" stroke-width="2" />
    
    <text x="200" y="40" text-anchor="middle" class="header-text">SVG文档结构</text>
    
    <g id="content-area">
        <text x="30" y="80" class="content-text">1. 声明和命名空间</text>
        <text x="30" y="110" class="content-text">2. 标题和描述</text>
        <text x="30" y="140" class="content-text">3. 定义部分(defs)</text>
        <text x="30" y="170" class="content-text">4. 主要图形内容</text>
        <text x="30" y="200" class="content-text">5. 样式和效果</text>
    </g>
</svg>

8.1.7 SVG可访问性

添加可访问性标记

SVG应该包含适当的可访问性标记:

html
<!-- 带有可访问性的SVG -->
<svg width="300" height="200" 
     viewBox="0 0 300 200"
     role="img"
     aria-labelledby="accessible-title"
     aria-describedby="accessible-desc">
    
    <title id="accessible-title">公司销售数据图表</title>
    <desc id="accessible-desc">
        这是一个柱状图,显示了公司2023年各季度的销售数据。
        第一季度销售额为100万,第二季度为150万,第三季度为120万,第四季度为180万。
    </desc>
    
    <!-- 图表内容 -->
    <g id="chart-content">
        <rect x="50" y="120" width="40" height="60" fill="blue" />
        <text x="70" y="195" text-anchor="middle" font-size="12">Q1</text>
        
        <rect x="110" y="80" width="40" height="100" fill="green" />
        <text x="130" y="195" text-anchor="middle" font-size="12">Q2</text>
        
        <rect x="170" y="100" width="40" height="80" fill="orange" />
        <text x="190" y="195" text-anchor="middle" font-size="12">Q3</text>
        
        <rect x="230" y="60" width="40" height="120" fill="red" />
        <text x="250" y="195" text-anchor="middle" font-size="12">Q4</text>
    </g>
</svg>

提供文本替代

html
<!-- 提供详细文本替代的SVG -->
<div class="svg-with-alternative">
    <svg width="250" height="150" viewBox="0 0 250 150" 
         role="img" aria-label="流程图示例">
        <rect x="20" y="40" width="80" height="40" fill="lightblue" stroke="blue" stroke-width="2" />
        <text x="60" y="65" text-anchor="middle" font-size="12">开始</text>
        
        <line x1="100" y1="60" x2="130" y2="60" stroke="black" stroke-width="2" marker-end="url(#arrowhead)" />
        
        <rect x="130" y="40" width="80" height="40" fill="lightgreen" stroke="green" stroke-width="2" />
        <text x="170" y="65" text-anchor="middle" font-size="12">处理</text>
        
        <defs>
            <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
                <polygon points="0 0, 10 3.5, 0 7" fill="black" />
            </marker>
        </defs>
    </svg>
    
    <!-- 文本替代内容 -->
    <div class="text-alternative">
        <h4>流程图文本描述</h4>
        <p>这是一个简单的流程图,包含两个步骤:</p>
        <ol>
            <li>开始:流程的起始点</li>
            <li>处理:执行主要处理逻辑</li>
        </ol>
        <p>两个步骤之间有箭头连接,表示执行顺序。</p>
    </div>
</div>

本节要点回顾

  • SVG基本概念:可缩放矢量图形,使用XML语法,基于数学描述
  • SVG优势:可无限缩放、文件小、可编辑、支持交互和动画
  • SVG与Canvas区别:矢量vs位图、DOM结构vs像素绘制、适用场景不同
  • SVG语法:遵循XML规范,需要命名空间声明,属性语法严格
  • 使用方式:内联SVG、外部文件、背景图像等多种方式

相关学习资源

常见问题FAQ

Q: SVG和Canvas应该如何选择?

A: SVG适合简单图形、图标、Logo等需要缩放的场景;Canvas适合复杂动画、游戏、图像处理等需要像素级控制的场景。

Q: SVG的viewBox属性如何理解?

A: viewBox定义了SVG的可视窗口,格式为"x y width height",可以实现图形的缩放、裁剪和定位效果。

Q: 如何让SVG图形具有更好的可访问性?

A: 应该添加title和desc元素,使用适当的ARIA属性,为复杂图形提供文本替代描述。

Q: SVG可以使用CSS样式吗?

A: 是的,SVG元素可以使用CSS样式,包括填充、描边、字体等属性,还可以使用CSS动画和过渡效果。

Q: 如何在HTML中引用外部SVG文件?

A: 可以使用img、object、embed标签引用外部SVG文件,或者使用CSS的background-image属性。


下一节预览:下一节我们将学习第8章第2节-SVG基本图形,重点介绍SVG中各种基本图形元素的语法和使用方法。