cover_image

矢量图SVG应用探索

狐友陈金凤 搜狐技术产品
2025年01月15日 23:31

随着计算机技术的不断发展,图形设计和多媒体制作领域对图像质量、可编辑性和跨平台兼容性的要求越来越高,而矢量图作为一种强大的图像类型,正好满足了这些需求。

在软件开发中,基于矢量图无限缩放性、小文件体积、高度可编辑性、跨平台兼容性和透明背景等独特优势,也会被大家广泛使用。

01

矢量图与SVG

矢量图,也称为向量图,是一种基于数学方程和几何属性的图形表示方法。它不同于位图,位图由像素组成,缩放时可能出现失真。而矢量图由一系列数学公式和参数定义,比如每个几何对象(如线段、曲线、多边形等)都有一组属性(如长度、角度、颜色、大小和屏幕位置等),加上数学方程,就可以绘制得到最终图形,并且缩放不失真。

矢量图有非常多的优点:

  1. 可以无限放大和缩小,且保持图像不变形,不改变清晰度;

  2. 矢量图的文件大小相对较小,因为它只存储图像的几何属性(如点、线、形状等),而不是像素数据。这使得矢量图在文件传输和存储时更加高效;

  3. 每个元素都是独立的实体,可以单独进行编辑和修改,如改变颜色、形状、大小等,而不会影响到其他部分,在图形设计和编辑中可以非常灵活;

  4. 清晰度与输出设备的分辨率无关,无论在哪个分辨率下显示或打印,都能保持其清晰度。

矢量图是基于点、线、形的几何图形,所以也有一些缺点:

  1. 几何图形绘制会导致画面表现力较弱;

  2. 与位图相比,表现色彩层次丰富的逼真图像效果存在局限,难以完全模拟真实世界的色彩和光影效果。

矢量图在标志设计,文字设计,图案设计,工程图等多个领域得到了广泛应用。其常见格式有如下几种:

  1.  SVG,基于XML的矢量图像格式,由W3C制定的开放矢量图形格式,作为网络矢量图形标准,旨在与DOM、CSS等Web技术协同工作,对网页设计和开发非常有利。作为文本格式,还可以被搜索引擎索引;

  2. EPS,用PostScript语言描述的一种ASCII图形文件格式;

  3. AI,Adobe公司矢量图形软件Illustrator的专用格式,支持非常复杂的矢量图形和插图,适用于专业设计和印刷行业;

  4. PDF,一种矢量文件格式,可以包含文本、图像、矢量图形等;

  5. CDR,CorelDRAW的专用矢量图形文件格式,适用于商标设计、插图绘制等领域。

其中,SVG(Scalable Vector Graphics)作为网络矢量图形标准,基于xml格式,不但拥有矢量图的优点,其文件结构也更清晰,更易于编辑和修改,在网页开发时被广泛使用。

制作SVG动画的工具多种多样,既包括专业的图形设计软件,也包括一些在线工具。如专业图形设计软件Adobe Illustrator,Inkscape,和在线工具 Shape Shifter,Haikei。

当然简单的SVG制作,可以不借助工具,直接在文本文件中编辑xml格式的svg文件即可,具体说明我们可以参考SVG1.1标准官方文档(https://www.w3.org/TR/SVG11/Overview.html)

举个简单的例子,我们将下列代码保存到 test1.svg 文件中:

<?xml version="1.0" standalone="no"?>
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">

  <desc>Example polygon01 - star and hexagon</desc>


  <rect x="1" y="1" width="1198" height="398"
        fill="none" stroke="blue" stroke-width="2" />



  <polygon fill="red" stroke="blue" stroke-width="10" 
            points="350,75  379,161 469,161 397,215
                    423,301 350,250 277,301 303,215
                    231,161 321,161"
 />

  <polygon fill="lime" stroke="blue" stroke-width="10" 
            points="850,75  958,137.5 958,262.5
                    850,325 742,262.6 742,137.5"
 />

</svg>

在浏览器打开test1.svg 文件,我们可以看到如下图形:

图片

SVG支持跨平台,但不同操作系统和浏览器版本可能对SVG文件的支持程度有所不同。

在macOS上,系统原生就支持SVG文件的显示,用户可以直接在Finder中预览SVG。

在Windows上,系统对SVG文件的原生支持相对有限,无法直接在资源管理器中预览SVG,但可以通过安装扩展插件来实现预览。

几乎所有主流的浏览器都支持SVG预览,所以开发者可以放心地使用SVG图形来创建和设计网页,而无需担心兼容性问题。

02

SVG图形绘制

SVG文档是有效的XML文档,遵循XML语法规则,使用XML命名空间来区分SVG元素和其他XML语言中的元素。

SVG包含一系列用于描述图形对象的元素,如<rect>、<circle>、<path>等。以上图test1.svg为例说明:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">



<svg width="1200" height="400" viewBox="0 0 1200 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">

  <desc>Example polygon01 - star and hexagon</desc>


  <rect x="1" y="1" width="1198" height="398"
        fill="none" stroke="blue" stroke-width="2" />



  <polygon fill="red" stroke="blue" stroke-width="10" 
            points="350,75  379,161 469,161 397,215
                    423,301 350,250 277,301 303,215
                    231,161 321,161"
 />

  <polygon fill="lime" stroke="blue" stroke-width="10" 
            points="850,75  958,137.5 958,262.5
                    850,325 742,262.6 742,137.5"
 />

</svg>

第一行包含了 XML 声明。请注意 standalone 属性!该属性规定此 SVG 文件是否是“独立的”,或含有对外部文件的引用。如果 standalone="no" 意味着 SVG 文档会引用一个外部文件,即第二和第三行引用的SVG DTD “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”。该 DTD 位于 W3C,含有所有允许的 SVG 元素。如果standalone="yes"表明这个XML文档是完整的,不依赖于任何外部定义的实体。实际上,即使省略SVG DTD的声明,系统也能正常显示SVG文件。

SVG 代码以 <svg> 元素开始,包括开启标签 <svg> 和关闭标签 </svg> 。

width 和 height 属性定义了视口大小,即网页或应用中的显示大小。如果这两个属性没有指定,SVG将不会有一个明确的尺寸,其大小由其嵌入的上下文来确定。

ViewBox属性定义了视口坐标系,即SVG画布的大小,SVG所有形状的坐标都是依据这个视口坐标系定义的。如果没有 viewBox 时,SVG的视口坐标系和视口大小相同,即SVG的左上角是(0,0),宽度和高度由 width 和 height 属性指定。视口坐标系里的坐标会根据视口大小进行缩放,所以坐标系和大小比例不同,会导致图形等比例变形。

xmlns 属性可定义 SVG 命名空间,version 属性可定义所使用的 SVG 版本。

<rect>,<polygon>是SVG的基本图形对象,它们除了包含统一的属性,还包含特有的属性。

fill 属性设置形状内的颜色。stroke 和 stroke-width 属性设置轮廓线的颜色和宽度。

矩形rect需额外指定width,height 和位置x,y。多边形<polygon>则需要额外指定各顶点的points属性。

2.1基本图形

SVG 有一些预定义的形状元素,方便开发者使用和操作:

  • 矩形<rect>

  • 圆形<circle>

  • 椭圆<ellipse>

  • 线<line>

  • 折线<polyline>

  • 多边形<polygon>

  • 路径<path>

基本形状对应的属性都比较通熟易懂,我们也可以在SVG1.1标准官方文档(https://www.w3.org/TR/SVG11/Overview.html)中查询其具体含义。下面的test2.svg中,展示了这些基本形状的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" viewBox="0 0 250 150"
    version="1.1" xmlns="http://www.w3.org/2000/svg">



  <rect x="10" y="10" width="60" height="40" stroke="black" fill="transparent" stroke-width="5"/>
  <rect x="80" y="10" rx="10" ry="10" width="40" height="40" stroke="black" fill="transparent" stroke-width="5"/>


  <circle cx="150" cy="30" r="20" stroke="red" fill="transparent" stroke-width="5"/>
  
  <ellipse cx="200" cy="30" rx="20" ry="5" stroke="red" fill="transparent" stroke-width="5"/>


  <line x1="10" x2="50" y1="70" y2="110" stroke="orange" stroke-width="5"/>
  
  <polyline points="50 70 55 80 60 75 65 90 70 85 75 100 80 95 85 110 90 105"
      stroke="orange" fill="transparent" stroke-width="5"/>



  <polygon points="130 65 135 85 150 85 140 95 145 110 130 100 115 110 120 95 110 85 125 85"
      stroke="green" fill="transparent" stroke-width="5"/>



  <path d="M164 80Q183 42 200 80T232 80" fill="none" stroke="blue" stroke-width="5"/>
</svg>


在浏览器打开test2.svg 文件,我们可以看到如下图形:

图片

其中路径<path>形状是最强大的SVG绘制元素,也是大家最常用的元素。接下来继续深入<path>的使用方法。

2.2Path

SVG使用<path>元素来定义复杂的形状和路径。<path>元素内通过命令指定如何绘制路径,这些命令如下:

1.M = moveto

  • 将画笔移动到指定的坐标位置,但不绘制线条。如果在一个路径数据字符串中多次使用,则每次都会重新定位画笔;

  • 示例:M 10 10 将画笔移动到坐标 (10, 10)。

2.L = lineto

  • 从当前位置绘制一条直线到指定的坐标位置;

  • 示例:M 10 10 L 90 90 从 (10, 10) 绘制一条直线到 (90, 90)。

3.H = horizontal lineto

  • 从当前位置绘制一条水平线到指定的 x 坐标位置;

  • 示例:M 10 10 H 90 从 (10, 10) 绘制一条水平线到 (90, 10)。

4.V = vertical lineto

  • 从当前位置绘制一条垂直线到指定的 y 坐标位置;

  • 示例:M 10 10 V 90 从 (10, 10) 绘制一条垂直线到 (10, 90)。

5.C = curveto

  • 通过指定的两个控制点绘制一条三次贝塞尔曲线到指定的终点;

  • 示例:M 10 10 C 40 10, 65 50, 90 90 从 (10, 10) 通过起点控制点 (40, 10) 和 终点控制点(65, 50) 绘制一条三次贝塞尔曲线到 (90, 90);

  • 查看曲线的控制点和绘制形状:

      图片



  • 在浏览器打开svg,查看形状如下:

图片

6.S = smooth curveto

  • 也是绘制一条三次贝塞尔曲线。如果S命令跟在一个C命令或者另一个S命令的后面,它的第一个控制点,就会被假设成前一个控制点的对称点。如果S命令单独使用,前面没有C命令或者另一个S命令,那么它的两个控制点就会被假设为同一个点;

  • 示例:假设前一个命令是 M 10 10 C 40 10, 65 50, 90 90,则  S 110 95 125 125 会从 (90, 90) 通过 起点控制点 (115, 130)(即 (65, 50) 的对称点,镜像点)和终点控制点(110, 95) 绘制一条曲线到 (125, 125);    

图片

  • 举例:假设前面没有C和S命令,单独使用命令S,则 M 90 90 S 115 95 125 125 会从 (90, 90) 通过控制点 (115, 95) 绘制一条曲线到 (125, 125)。

图片

7.Q = quadratic Belzier curve

  • 通过指定的一个控制点绘制一条二次贝塞尔曲线到指定的终点;

  • 示例:M 90 90 Q 115 95 125 125 从 (90, 90) 通过控制点 (115, 95) 绘制一条二次贝塞尔曲线到 (125, 125)。从图形可以看出来,和上一个S命令单独绘制时是一样的。

    图片

8.T = smooth quadratic Belzier curveto

  • 绘制一条二次贝塞尔曲线。和之前的命令S类似,命令T会通过前一个命令Q或命令T的控制点,镜像得到它的控制点。如果单独使用命令T,那么控制点就会被认为和终点是同一个点,将会画出一条直线;

  • 示例:假设前一个命令是 M 90 90 Q 115 95 125 125,则 T 105 125 会从 (125, 125) 通过控制点 (115, 95) 的镜像点(135, 155) 绘制一条曲线到 (105, 125)。

    图片

9.A = elliptical Arc

  • 绘制一个椭圆弧。命令需要指定半径、旋转角度、是否大弧、是否顺时针以及终点坐标:A rx ry x-axis-rotation large-arc-flag sweep-flag x y;

  • 示例:M 10 20 A 40 20 0 1 1 30 40 从 (10, 20) 绘制一个X轴半径40,Y轴半径20,无旋转,大弧,顺时针,到 (30, 40)的椭圆弧。

图片

10.Z = closepath

  • 关闭路径,从当前位置绘制一条直线到路径的起始点;

  • 示例:M 10 20 A 40 20 0 1 1 30 40  Z 绘制椭圆弧并闭合路径。对比上图,可以看到多了一条闭合直线。

    图片

这些命令字母都支持大小写,大写表示绝对定位小写表示相对定位

比如 M 20 10 L 30 30 L 10 30 Z 和 m 20 10 l 10 20 l -20 0 z 画出来的是同一个三角形:

       图片

对于复杂的路径,我们很难通过命令和坐标直接画出来,需要借助SVG Path编辑器。市面上有很多强大的SVG编辑器,它们一般需要安装软件或者付费。给大家推荐一款在线,免费,操作简单的SVG Path编辑器:https://yqnn.github.io/svg-path-editor/

我们可以通过Path编辑器创建,修改复杂的形状,如下2张图演示了电池形状的绘制:

图片

图片

2.3文本

<text>元素可以用于绘制文本。其属性x和y指定了文本在视口中显示的位置。下面的test3.svg中,展示了文本的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

    
    <rect width="150" height="50" style="fill:rgb(0,255,255);stroke-width:1;stroke:rgb(0,0,0)"/>
    <text x="20" y="20">Hello World!</text>
</svg>


在浏览器打开test3.svg 文件,我们可以看到如下图形和文字:

图片

元素可以把文本对齐到路径,让文本会环绕路径,或顺着路径走。下面的test4.svg中,展示了文本环绕路径的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink">



    <rect width="150" height="50" style="fill:rgb(0,255,255);stroke-width:1;stroke:rgb(0,0,0)"/>
    <text x="20" y="20">Hello World!</text>
    
    <path id="my_path" d="M 30,30 C 50,50 90,50 110,30" fill="transparent" />
    <text>
      <textPath xlink:href="#my_path">Hello path!</textPath>
    </text>
</svg>


test4.svg中新增加了 xmlns:xlink="http://www.w3.org/1999/xlink" 的命名空间声明,它指定了xlink前缀用于引用XLink命名空间中的元素和属性。XLink是一个W3C推荐标准,用于定义在XML文档中链接资源的方式。在SVG中,它主要用于定义元素之间的链接,如<a>元素中的xlink:href属性,用于指定链接目标。

<textPath>通过xlink:href属性,指定了一个文本的绘制路径。在浏览器打开test4.svg 文件,我们可以看到如下图形和文字:

图片

文本元素和形状元素类似,可以通过属性fill给文本填充颜色,属性stroke给文本描边,也可以引用渐变色。 <linearGradient>可用来定义 SVG 的线性渐变。<redialGradient>用来定义放射性渐变。下面的test5.svg文件中,展示了文本填充颜色的方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" >



<text style="fill:rgb(0,255,255);stroke-width:1;stroke:rgb(0,0,0)"
          x="60" y="15" >
Hello World!</text>


<defs>
<linearGradient id="testLinear" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(100,100,100); stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(0,255,255); stop-opacity:1"/>
</linearGradient>
</defs>

<text x="20" y="40" style="fill:url(#testLinear)">Hello World!</text>
<ellipse cx="80" cy="100" rx="60" ry="50" style="fill:url(#testLinear)"/>


<defs>
<radialGradient id="testRadial" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(100,100,100); stop-opacity:0"/>
<stop offset="100%" style="stop-color:rgb(0,255,255); stop-opacity:1"/>
</radialGradient>
</defs>

<text x="180" y="40" style="fill:url(#testRadial)">Hello World!</text>
<ellipse cx="230" cy="100" rx="60" ry="50" style="fill:url(#testRadial)"/>
</svg>

<defs>元素用来预定义属性,后续这些属性可以被其它元素重复引用。每个属性都用一个唯一的id。

<linearGradient>元素定义了一个 id 为"testLinear"的线性渐变色。x1、y1、x2、y2 属性可定义渐变的开始和结束位置。

<stop>结点通过位置 offset偏移属性,stop-color颜色属性和stop-opacity透明属性来说明在渐变的特定位置上应该是什么颜色;

<text>和<ellipse>则通过style="fill:url(#testlinear)" 属性把id为"testlinear"的线性渐变色引入到文本和椭圆中。

<radialGradient>元素定义了一个 id 为"testRadial"的发射性渐变色,这种渐变从中心点向外辐射。cx 和 cy 属性定义了渐变中心点的坐标,r 属性定义了渐变圆的半径,fx 和 fy 属性定义了渐变焦点的坐标。

当fx 和 fy 与cx 和 cy 相等时,渐变将呈现为均匀的同心圆辐射。

在浏览器打开test5.svg 文件,我们可以看到如下图形和文字:

图片

当fx 和 fy 与cx 和 cy 不相等,渐变将会呈现为椭圆形辐射,其中焦点和中心点之间的连线定义了渐变的主轴。

将test5.svg 文件中<radialGradient>属性改为 fx="40%" fy="60%",我们可以看到渐变焦点和渐变改变了:

图片

2.4图形

<image>可以通过xlink:href属性,将一幅jpg图像呈现在SVG对象,部分解决了SVG不能绘制色彩层次丰富的逼真图像,但引入的图片放大时清晰度会变差。

下面的test6.svg文件中,展示了显示图片的方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink">



    <image xlink:href="https://developer.android.google.cn/static/images/guide/topics/graphics/ic_battery_charging_80_black_24dp.png" 
            x="10" y="10" height="50" />



    <image xlink:href="https://img.doc.xuehai.net/pic/12c9c948ead6729ce54c36dedef847ba390025b9/1-1215-jpg_6-1620-0-0-1620.jpg" 
            x="10" y="60" width="150px"/>
   
</svg>

在浏览器打开test6.svg 文件,我们可以看到引入的文件被显示出来:

图片

SVG还有非常丰富的命令,包括滤镜,字体,链接,脚本和CSS,大家可以根据SVG1.1标准官方文档要求进行使用。

03

SVG动画绘制

SVG 支持动画,包含4个关键动画元素和一系列特定的属性,其具体说明可参考SVG1.1标准官方文档(https://www.w3.org/TR/SVG11/Overview.html)下面分别对所有动画元素和关键属性进行说明。

3.1animate

animate 元素用于在SVG元素上创建动画效果,可以将任何数值属性(如位置、大小、颜色等)转换成动画。它可以在属性中指定动画的持续时间、重复次数、动画的起始值和结束值等。其效果和Android的属性动画一样。

下面的test7.svg文件中,展示了平移动画的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" >



    <circle cx="100" cy="100" r="40" stroke="black" stroke-width="3" fill="red">
        <animate attributeName="cx" from="50" to="150" dur="2s" repeatCount="indefinite" />
    </circle>
</svg>

在浏览器打开test7.svg 文件,我们可以看到,圆的中心点cx会在2秒内从50移动到150,并无限重复这个变化:

图片

3.2set

set 元素用于在特定时间将SVG元素的属性值设置为一个固定值,通常用于在动画序列中改变属性值而不进行过渡动画。

下面的test8.svg文件中,展示了平移动画set动画的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" >



    <circle cx="100" cy="100" r="40" stroke="black" stroke-width="3" fill="red">
        <set attributeName="fill" to="blue" begin="1s" dur="1s" />
    </circle>
</svg>

在浏览器打开test8.svg 文件,我们可以看到,圆的填充颜色在1秒后开始变为蓝色,并保持1秒后变回红色:

图片

3.3animateMotion

animateMotion 元素用于沿着一个路径移动SVG元素。它需要一个<mpath>元素来指定路径,或者直接在animateMotion内部使用<path>元素定义路径。

下面的test9.svg文件中,展示了path动画的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" >



  <path id="motionPath" d="M 10,80 Q 95,10 180,80" />
  <circle cx="0" cy="0" r="10" fill="red">
    <animateMotion dur="5s" repeatCount="indefinite">
      <mpath href="#motionPath" />
    </animateMotion>
  </circle>
</svg>


从SVG 1.1开始,xlink:href 已经被简化为 href,不再需要显式地声明 xmlns:xlink 命名空间。如果要使用XLink的其他功能,仍然需要显式地声明 xmlns:xlink 命名空间。在浏览器打开test9.svg 文件,我们可以看到,圆沿着定义的二次贝塞尔曲线路径移动,并无限重复:

图片

3.4animateTransform

animateTransform 元素用于对SVG元素应用变换动画,如旋转、缩放、平移等。它允许你指定变换类型、变换的起始值和结束值等。其效果和Android的补间动画一样。

下面的test10.svg文件中,展示了变换动画的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" >



  <rect x="50" y="50" width="50" height="50" fill="blue">
    <animateTransform attributeName="transform" attributeType="XML"
                      type="rotate"
                      from="0 75 75"
                      to="360 75 75"
                      dur="10s"
                      repeatCount="indefinite"/>

  </rect>
</svg>

在浏览器打开test10.svg 文件,我们可以看到,矩形围绕其中心点(75,75)旋转360度,动画持续10秒,并无限重复:

图片

如果需要对图形进行变换,但不要产生动画效果,可以直接使用元素的transform属性。

下面的test10_2.svg文件中,展示了元素变换的绘制方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" >


  <rect x="50" y="50" width="50" height="50" fill="blue" 
        transform="rotate(15 75 75)" />
</svg>

在浏览器打开test10_2.svg 文件,我们可以看到,矩形围绕其中心点(75,75)旋转15度,静态显示,效果如下图:

图片

协议中还提及了一个animateColor动画,但这个动画很少被使用,已经被废弃,大家可以通过animate实现animateColor动画。

04

网页中的SVG

SVG 是W3C制定的网络矢量图形标准,其目标之一是矢量图能与DOM、CSS等Web技术协同工作,所以在网页中使用SVG非常便利,且浏览器的兼容性也非常好。

4.1JavaScript控制

SVG图像具有交互性,在网页中可以通过JavaScript代码控制SVG动画效果、用户交互等。例如,用户可以与SVG图像进行点击、悬停等操作,从而触发特定的动作或动画。

下面的test11.html文件中,展示了JavaScript代码控制SVG的方法:

<html>
    <header>
        <title>SVG Test</title>
    </header>
    <body>
        <svg id="circleSvg" width="200" height="200">
            <circle cx="100" cy="100" r="50" fill="#ff9933"/>
        </svg>
        
        <script>
            var circle = document.querySelector("#circleSvg circle");
            circle.addEventListener("click"function() {
                circle.setAttribute("fill""#3366cc");
            });
        </script>



    </body>
</html>

在浏览器打开test11.html文件,我们可以看到,当用户点击SVG中的圆形时,圆形的填充颜色会发生变化:

图片

4.2CSS控制

SVG也支持通过CSS控制SVG的动画,包括位置变化、颜色变化、形状变化等。

下面的test12.html文件中,展示了CSS代码控制SVG的方法:

<html>
    <header>
        <title>SVG Test</title>
    </header>
    <body>
        <svg id="rectSvg" width="200" height="200">
            <rect x="50" y="50" width="50" height="50" fill="#ff9933"/>
        </svg>
           
        <style>
            #rectSvg rect {
              transformrotate(0deg);
              transition: all 1s;
            }
            
            #rectSvg:hover rect {
              transform-origin50px 30px;
              transformrotate(45deg);
            }
        </style>



    </body>
</html>

例子中,通过CSS选择器 #rectSvg rect,为rectSvg元素内的所有<rect>元素确定初始状态为:矩形不进行旋转,transform属性变化时,过渡效果持续1秒,即属性变化会以1秒的动画形式显示。

通过CSS伪类选择器 #rectSvg:hover rect,设置鼠标悬停在rectSvg的矩形中时,矩形以原点(50px, 30px)进行45度旋转。

在浏览器打开test12.html文件,我们可以看到,当用户将鼠标悬停在SVG矩形上时,矩形会旋转45度,移开鼠标时矩形会恢复位置:

图片

4.3事件监听

SVG支持多种事件监听,如点击、悬停、移动等。通过为SVG元素添加事件监听器,可以实现复杂的交互逻辑。

下面的test13.html文件中,展示了SVG的事件监听方法:

<html>
    <header>
        <title>SVG Test</title>
    </header>
    <body>
        <svg width="200" height="200">
            <rect id="myRect" x="10" y="10" width="80" height="80" fill="red" 
              onclick="changeColor()" onmouseover="grow()" 
              onmouseout="shrink()"/>

        </svg>
           
        <script>
            function changeColor() {
              var rect = document.getElementById("myRect");
              var color = rect.getAttribute("fill") === "red" ? "green" : "red";
              rect.setAttribute("fill", color);
            }
            
            function grow() {
              var rect = document.getElementById("myRect");
              rect.setAttribute("width""100");
              rect.setAttribute("height""100");
            }
            
            function shrink() {
              var rect = document.getElementById("myRect");
              rect.setAttribute("width""80");
              rect.setAttribute("height""80");
            }
        </script>



    </body>
</html>

在浏览器打开test13.html文件,我们可以看到,当用户将鼠标悬停在矩形上时,矩形会变大;当用户点击矩形时,矩形的颜色会改变;当用户将鼠标移开矩形时,矩形会恢复原来的大小:

图片

4.4SVG动态互动

SVG本身也支持脚本控制,把脚本放在SVG中,可以让SVG本身具备了动态交互的能力,无需依赖外部框架。

下面的test14.svg文件中,展示了SVG文件内的事件监听方法:

<?xml version="1.0" standalone="no"?>
<svg width="250" height="150" version="1.1" 
    xmlns="http://www.w3.org/2000/svg" >



    <rect id="myRect" x="10" y="10" width="80" height="80" fill="red" 
      onclick="changeColor()" onmouseover="grow()" 
      onmouseout="shrink()"/>

 
    <script>
        function changeColor() {
            var rect = document.getElementById("myRect");
            var color = rect.getAttribute("fill") === "red" ? "green" : "red";
            rect.setAttribute("fill", color);
        }
        
        function grow() {
            var rect = document.getElementById("myRect");
            rect.setAttribute("width""100");
            rect.setAttribute("height""100");
        }
        
        function shrink() {
            var rect = document.getElementById("myRect");
            rect.setAttribute("width""80");
            rect.setAttribute("height""80");
        }
    </script>

</svg>

在浏览器打开test14.svg文件,我们可以看到它的动画效果和test13.html的效果一样:悬停变大,点击变色。

浏览器对SVG内的脚本支持程度不同,会有兼容性问题,所以对于简单的交互逻辑和紧凑的SVG图形,可以考虑将脚本嵌入SVG中,提高SVG图形的独立性;而对于复杂的交互逻辑和大型SVG图形,则更适合在HTML中通过脚本进行控制,避免出现大量兼容性问题。

4.5嵌入SVG文件

前面几个例子都是在网页中引入svg标签,这种方式的优点是可以对SVG元素直接应用CSS和JavaScript,比较灵活。但在网页应用中使用SVG最常见方式是引入SVG文件,这种方式可以减少SVG的复杂性,保持SVG的独立性和复用性。

html中可以通过<object>,<iframe>,<embed>,<img>标签引入SVG文件,下面的test15.html文件中,展示了引入SVG文件的方法:

<html>
    <header>
        <title>SVG Test</title>
    </header>
    <body>
        <ul id="unsortedList">
            <li>object<br>
                
                <object type="image/svg+xml" data="test14.svg" id="svgObject"></object>
            </li>
            <li>iframe<br>
                
                <iframe src="test14.svg" >iframe svg</iframe>
            </li>
            <li>embed<br>
                
                <embed type="image/svg+xml" src="test14.svg" >
            </li>
            <li>Date<br>
                
                <img src="test14.svg" alt="SVG image">
            </li>
        </ul>
    </body>
</html>

选择哪种方式取决于具体需求,如果只是需要将SVG作为静态图像展示,可以使用<img>标签,因为它不支持SVG中的脚本,而<embed>标签不支持所有浏览器,兼容性不够好,所有建议使用<object>或<iframe>标签。

在浏览器打开test15.html文件,我们可以看到4个和test14.svg一样的矩形。其中<img>标签的SVG矩形操作时不会有缩放和变色效果,其它几个矩形都有悬停变大,点击变色的效果。

图片


05

总结

网页开发中使用SVG有非常多好处,比如,可以提高图像质量,无限放大或缩小图片都能保持清晰锐利;还可以减小文件大小,比位图图形(如BMP,JPEG、PNG等)小非常多;还可以增加图片交互性,能通过JavaScript和CSS动画等实现各种互动效果。

SVG作为一个矢量图形标准,现在不仅包括了矢量图形,还包含文字,图片,滤镜,字体,链接,脚本,CSS和动画等功能。这些特性让SVG变得强大的同时,也使得SVG渲染器的开发变得过于复杂。

现在只有浏览器支持全功能的 SVG 渲染器(不同浏览器可能有兼容问题),其它SVG渲染器要么只部分支持(比如不支持动画),要么支持一个比SVG更简单的矢量图格式(比如Android的Vector)。

在跨端应用中使用SVG时,我们不能仅仅考虑网页端效果,还需要综合考虑其它端的支持情况,以选择合适的SVG特性进行使用,发挥出SVG的优势。



继续滑动看下一个
搜狐技术产品
向上滑动看下一个