SVG 基础

使用XML描述的矢量文件
W3C标准(1.1): http://www.w3.org/TR/SVG11/
浏览器支持情况: http://caniuse.com/#cats=SVG

目录 [1]
[TOC]

一、SVG基本概念

1.1SVG的使用方式

1.1.1 浏览器直接打开

1.1.2 在HTML中使用<img>标签使用

<img src="images/icon.svg" width="50" height="50">

1.1.3 直接在HTML中使用SVG标签

1.1.4 作为CSS背景

.container{
  background: white url(bg.svg) repeat;

1.2 基本图形和属性

<circle>
<ellipse>
<polyline>
<polygon>

stroke
stroke-width
transform

<line x1="start-x" y1="start-y" x2="end-x" y2="end-y"/> 直线:起点(start-x,start-y),终点(end-x,end-y) <rect x="left-x" y="top-y" width="width" height="height"/> 矩形:左上角(left-x,top-y),宽高width,height <circle cx="center-x" cy="center-y" r="radius"/> 圆: 圆心(center-x, center-y) 半径 r <ellipse cx="center-x" cy="center-y" rx="x-radius" ry="y-radius"/> 椭圆: 圆心(center-x, center-y) xy轴半径 rx, ry <polygon points="points-list"/> 多边形: 由一系列坐标组成, points-list: x1 y1 x2 y2 x3 y3 .... <polyline points="points-list"/> 折线: 由一系列坐标组成, points-list: x1 y1 x2 y2 x3 y3 ....

<rect x="100" y="100" width="200" height="100" rx="30" ry="30" fill="red" />

rx\ry表示圆角度数,如果只给一个值,另一个也会用到同一个值。

1.2.2 <circle>

<rect x="100" y="100" width="400" height="200" fill="#FFB3AE" stroke="#971817" stroke-width="10" transform="rotate(30)" />

1.2.8 实例

<svg xmlns="http://www.w3.org/2000/svg">
    <rect x="10" y="10" rx="5" ry="5" width="150" height="100" stroke="red" fill="none"></rect>
    <circle cx="250" cy="60" r="50" stroke="red" fill="none"></circle>
    <ellipse cx="400" cy="60" rx="70" ry="50" stroke="red" fill="none"></ellipse>
    <line x1="10" y1="120" x2="160" y2="220" stroke="red"></line>
    <polyline points="250 120 300 220 200 220" stroke="red" fill="none"></polyline>
    <polygon points="250 120 300 220 200 220" stroke="red" stroke-width="5" fill="yellow" transform="translate(150 0)"></polygon>
<svg id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 500" preserveAspectRatio="xMidYMax meet">
                <!--Face-->
                <circle cx="100" cy="100" r="90" fill="#39F"></circle>
                <!--Eyes-->
                <circle cx="70" cy="80" r="20" fill="white"></circle>
                <circle cx="130" cy="80" r="20" fill="white"></circle>
                <circle cx="65" cy="75" r="10" fill="black"></circle>
                <circle cx="125" cy="75" r="10" fill="black"></circle>
                <!--Smile-->
                <path d="M 50 140 A 60 60 0 0 0 150 140" stroke="white" stroke-width="3" fill="none"></path>
                <rect id="viewBoxIndicator" stroke="red" stroke-width="3.5" fill="none" x="0" y="0" width="600" height="500"></rect>
<svg xmlns="...">
    <g stroke="green" fill="none">
        <rect x="100" y="50" width="100" height="50"></rect>
        <rect x="140" y="100" width="20" height="120"></rect>

实例:查看原代码

<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="600" viewBox="-200.5 -100.5 1000 600">
            <g id="coord">
                <line x1="0" y1="0" x2="300" y2="0"></line>
                <line x1="0" y1="0" x2="0" y2="300"></line>
                <circle cx="0" cy="0" r="2"></circle>
                <circle cx="100" cy="0" r="2"></circle>
                <circle cx="200" cy="0" r="2"></circle>
                <circle cx="300" cy="0" r="2"></circle>
                <circle cx="0" cy="200" r="2"></circle>
                <circle cx="0" cy="100" r="2"></circle>
                <circle cx="0" cy="300" r="2"></circle>
        </defs>
        <text fill="black" x="-55" y="5">Group</text>
        <use xlink:href="#coord" stroke="black" fill="black"></use>
        <g id="a" stroke="red" fill="red" transform="translate(50, 50)">
            <text x="5" y="20">a</text>
            <use xlink:href="#coord"></use>
            <g id="b" stroke="blue" fill="blue" transform="translate(50, 50)">
                <text x="5" y="20">b</text>
                <use xlink:href="#coord"></use>
                <g id="c" stroke="green" fill="green" transform="translate(50, 50) rotate(30)">
                    <text x="5" y="20">c</text>
                    <use xlink:href="#coord"></use>
            <g id="d" stroke="orange" fill="orange" transform="translate(150, 150)">
                <text x="5" y="20">d</text>
                <use xlink:href="#coord"></use>
<svg xmlns="http://www.w3.org/2000/svg">
        <linearGradient id="grad1" x1="0" y1="0" x2="1" y2="1">  <--可以添加gradientUnits的属性来改变坐标-->
            <stop offest="0" stop-color="#1497fc" />
            <stop offest="0.5" stop-color="#a469be" />
            <stop offest="1" stop-color="#ff8c00" />
        </linerGradient>
    </defs>
    <rect x="100" y="100" fill="url(#grad1)" width="200" height="150" />
<svg xmlns="http://www.w3.org/2000/svg">
        <radialGradient id="grad2" cx="0.5" cy="0.5" r="0.5" fx="0.6" fy="0.3"> <--fx和fy表示偏移-->
            <stop offest="0" stop-color="rgb(20,151,252)" />
            <stop offest="0.5" stop-color="rgb(164,105,190)" />
            <stop offest="1" stop-color="rgb(255,140,0)" />
        </radialGradient>
    </defs>
    <rect x="100" y="100" fill="url(#grad2)" width="200" height="150" />
patternUnits:
objectBoundingBox : (默认)为容器百分比
userSpaceOnUse : width 和 height 以世界坐标系为准,为宽度、高度
patternContentUnits:
userSpaceOnUse : (默认)为以世界坐标系为准
objectBoundingBox : pattern 的子元素(这里指 circle 和 polygon,尺寸属性为 rect 的百分比)
一般情况下 patternContentUnits 为 objectBoundingBox 时,patternUnits 也为 objectBoundingBox,好处理
<svg xmlns="http://www.w3.org/2000/svg">
        <pattern id="p1" x="0" y="0" width="0.2" height="0.2" > 
            <circle cx="10" cy="10" r="5" fill="red"></circle>
            <polygon points="30 10 60 50 0 50" fill="green"></polygon>
        </pattern>
    </defs>
    <rect x="100" y="100" width="400" height="300"  fill="url(#p1)" stroke="blue"></rect>

他还有个patternContentUnits="objectBoundingBox/userSpaceOnUse"属性:

<pattern id="p1" x="0" y="0" width="0.2" height="0.2" patternUnits="objectBoundingBox" patternContentUnits="objectBoundingBox"> 

四、Path高级教程

4.1 Path概述

  • 强大的绘图工具
  • 规范:https://www.w3.org/TR/SVG/paths.html
  • 由命令及其参数组成的字符串,如:
  • <path d="M0,0L10,20C30-10,40,20,100,100" stroke="red">
    <tiger.svg>

    <path d="M0,0L10,20C30-10,40,20,100,100" stroke="red">
    <path d="M 0 0 L 10 20 C 30 -10 40 20 100 100" stroke="red">
    <path d="M 0 0,L 10 20,C 30 -10 40 20 100 100" stroke="red">

    path命令汇总
    凡是出现大写字母表示后续坐标为绝对坐标, 凡是小写字母都代表相对于上一个坐标的相对位移。 Z 同 z 无差别,因为表示闭合,其后不用跟坐标。 C/c (cx1 cy1 cx2 cy2 x y)+ 从当前点画一条到(x, y)的三次贝塞尔曲线, 曲线的开始控制点和终点控制点为别为 (cx1, cy1), (cx2, cy2). S/s (cx2 cy2 x y)+ 此命令只能跟在 C 命令后使用, 假设 C 命令生成曲线 s, S 命令的作用是再画一条到 (x, y)的三次贝塞尔曲线, 曲线的终点控制点是 (cx2, cy2), 曲线的开始控制点是 s 的终点控制点关于 s 终点的对称点. Q/q (cx,cy,x,y)+ 从当前点画一条到(x, y)的二次贝塞尔曲线, 曲线的控制点为(cx, cy) T/t (x,y)+ 此命令只能跟在 Q 命令后使用, 假设 Q 命令生成曲线 s, T 命令的作用是从 s 的终点再画一条到(x y)的二次贝塞尔曲线, 曲线的控制点为 s 控制点关于 s 终点的对称点. T 命令生成的曲线会非常平滑 A(a) rx ry x-axis-rotation large-arc sweep x y 画一段到(x,y)的椭圆弧. 椭圆弧的 x, y 轴半径分别为 rx,ry. 椭圆相对于 x 轴旋转 x-axis-rotation 度. large-arc=0表明弧线小于180读, large-arc=1表示弧线大于180度. sweep=0表明弧线逆时针旋转, sweep=1表明弧线顺时间旋转. 具体解释看如何绘制椭圆弧 ry - (radius-y)弧线所在椭圆的Y半轴长 xr - (xAxis-rotation)弧线所在椭圆的长轴角度,那么 x-axis-rotation 又是什么意思呢? b, c, d, e 产生的前提是 椭圆的 x 轴与用户坐标系的 x 轴是平行的.
    F 图表示椭圆 x 轴相对于用户坐标系的 x 轴旋转30度所产生的椭圆弧. 灰色的部分表示原来产生的椭圆弧. laf - (large-arc-flag)是否选择弧长较长的那一段 sf - (sweep-flag)是否选择逆时针方向的那一段弧 x,y - 弧的终点位置
    <svg xmlns="http://www.w3.org/2000/svg">
            <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
                <path stroke="#f0f0f0" fill="none" d="M0,0H20V20"></path>
            </pattern>
        </defs>
        <rect width= "100%" height="100%" fill="url(#grid)"></rect>
    
    <text x="100" y="100" dx="20 40 60 80 100" dy="20 20 20 20 20" style="font-size: 50px">ABCDE</text>  //dx让文字前间距偏移;dy让文字上间距偏移
    <path d="M 0 100 H 200 M 100 0 H 200" transform="translate(0, 60)" stroke="red"> </path>     //辅助线
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Examples</title>
    <meta name="description" content="">
    <meta name="keywords" content="">
    <link href="" rel="stylesheet">
    </head>
    <!-- pattern 笔刷 -->
    <svg xmlns="http;//www.w3.org/2000/svg" width="100%" height="1000">
        <defs> <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
                <path stroke="#F0F0F0" fill="none" d="M 0 0,H 20,V 20"></path>
        </pattern> </defs>
        <rect width="100%" height="1000" fill="url(#grid)"></rect>
        <text id="sintext" x='100' y='160' style="font-size:16px;font-family:'Arial';"></text>
        <path d="M 100 0,V 200,M 0 100,H 800" transform="translate(0,60)" stroke="red"></path>
    <script type="text/javascript">
        var text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        var n = text.length;
        var x = [];
        var i = n;
        var y = null;
        var s = 100,w = 0.02,t = 0;
        while(i--){
            x.push(10);
            var tspan = document.createElementNS('http://www.w3.org/2000/svg','tspan');
            tspan.textContent = text[n - i - 1];
            sintext.appendChild(tspan);
            var h = Math.round(360 / 26 * i);
            tspan.setAttribute('fill','hsl(' + h + ',100%,100%)');
        function arrange(t){
            y = [];
            var ly = 0,cy;
            for(i = 0;i < n; ++i){
                cy = -s * Math.sin(w* i *20 +t);
                y.push(cy - ly);
                ly = cy;
        function render(){
            sintext.setAttribute('dx',x.join(' '));
            sintext.setAttribute('dy',y.join(' '));
        function frame(){
            t += 0.01;
            arrange(t);
            render();
            requestAnimationFrame(frame);
        arrange(0);
        render();
        frame();
    </script>   
    </body>
    </html>
    <tspan>标签

    <text x="100" y="100" style="font-size:50px; font-family:'Arial';">
        <tspan fill="red">AB</tspan><tspan stroke="green" stroke-width="2" fill="none">CDE</tspan>
    </text>
    
  • 5.3.1 使用方法
  • <path id="path1" d="M 100 200 Q 200 100 300 200 T 500 200" stroke="rgb(0,255,0)" fill="none" />
    <text style="font-size: 24px;">
        <textPath xlink:href="#path1">
            这个文字先上去又下来了!
        </textPath>
    </text>
    

    5.3.2 布局原理

    <svg width="1000" height="1000">
        <path id="path1" d="M100 200Q200 100 300 200T500 200" stroke="rgb(0,255,0)" fill="none"></path>
        <text style="font-size:24px;" x="0" y="0" text-anchor=“start” >  
        //这里的x控制文字的水平位置,y没有实际作用;text-anchor表示文字的起始位置,三个值:start(文本起点与路径起始点对齐)、minddle(文本中点与路径起始点对齐)、end;
            <textPath xlink:href="#path1" startOffset=“0%”>
            //startOffset:0~100%,文本在路径上的位置,50%表示在路径的中点
               这个文字先上去又下来了!
            </textPath>
        </text>
    
  • dx、dy属性
    切线和法线方向的偏移
  • <svg width="1000" height="1000">
        <path id="path1" d="M100 200Q200 100 300 200T500 200" stroke="rgb(0,255,0)" fill="none"></path>
        <text style="font-size:24px;" x="0" y="0" text-anchor=“start” >  
            <textPath dominant-baseline="central" startOffset=“50%” xlink:href="#path1" >
                <tspan> 这个文字先</tspan>
                <tspan dy="-30" dx="20" fill="blue">上去</tspan>
                <tspan dy="30" dx="20" > ,又</tspan>
                <tspan dy="30" fill="red">下来</tspan>
                <tspan dy="-30">了!</tspan>
            </textPath>
        </text>
    
  • target 指定打开目标
  • <svg xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="1000">
        <a xlink:href="http://www.baidu.com" xlink:title="ceshi" target="_blank">
            <circle cx="300" cy="150" r="50" fill="rgba(0, 255, 0, .5)" stroke="rgb(0, 200, 0)" stroke-width="2"></circle>
    

    当SVG独立存在时,需要xmlns:xlink="http://www.w3.org/1999/xlink"声明xlink的名称空间。

    六、图形引用、裁切和蒙版

    6.1 <use>标签创建图形引用

    xlink:href="#id"
    <use xlink:href="#real" transform="scale(1,-1)" />
    

    6.2 <cilp>标签裁切图形

    clip-path="url(#clip-id)"
    <clipPath id="light-clip">
        <polygon points="0 0 -301 -15 -301 15" fill="rgba(255,0,0,.5)">
          <!-- 添加动画 -->
          <animateTransform attributeName="transform" attributeType="XML" type="rotate" form="0" to="360" dur="10s" repeatCount="indefinite"></animateTransform>
        </polygon>
          <circle cx="0" cy="0" r="4"></circle>
    </clipPath>
          <!-- 使用clip-path="url(#light-clip)"取三角形和椭圆的交集 -->
    <ellipse cx="0" cy="0" rx="300" ry="100" fill="url(#light-color)" clip-path="url(#light-clip)"></ellipse>
    

    6.3 <mask> 标签创建蒙版

    mask="url(#mask-id)"
    <g id="reflact" transform="translate(0 100)" mask="url(#fading)">
      <!-- 绘制线性渐变 -->
        <linearGradient id="fade" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stop-color="rgba(255,255,255,.3)"></stop>
        <stop offset="0.5" stop-color="rgba(255,255,255,0)"></stop>
      </linearGradient>
      <mask id="fading">
        <rect x="-400" y="-50" width="800" height="300" fill="url(#fade)"></rect>
      </mask>
      </defs>
      <use xlink:href="#real" transform="scale(1,-1)" />
    

    查看源文件

    七、SVG动画

    7.1 动画原理

    <animate>、<animateTransform>、<animateMotion>...
  • 动画元素、属性定位以及动画参数设置
    ‣ attributeName、attributeType
    ‣ form、to、dur、repeatCount、fill...
    ‣ calcMode...
  • 7.2.1 定位动画目标

  • internal Resource Identifier定位
  • <animate xlink:href="url(#rect1)"></animate>
    
  • 被包含在目标元素里
  • <rect x="0">
      <animate></animate>
    </rect>
    

    7.2.2 基本动画<animate>

  • 设置要进行动画的属性以及变化范围、时间长度
  • <animate xlink:href="url(#rect1)">
      attributeType="XML"
      attributeName="x"
      from="10"
      to="110"
      dur="3s"
    </animate>
    

    实例,写一个从左到右移动,颜色由红色变为黄色的动画:

    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
      <rect x="100" y="100" width="100" height="100" fill="red">
        <animate attributeType="XML" attributeName="x" from="100" to="500" dur="3s" fill="freeze" > </animate>  
        <-- repeatCount="indefinite"  //无限次重复,可是设置整数-->
        <animate attributeType="XML" attributeName="fill" from="red" to="yellow" dur="3s" fill="freeze"></animate>
      </rect>
    

    让矩形来回摆动且颜色跟着切换:

    <animate id="goRight" attributeType="XML" 
          begin="0; goLeft.end + 1s" 
          attributeName="x" from="100" to="500" dur="3s" fill="freeze"></animate>
    <animate id="goLeft" attributeType="XML" 
          begin="goRight.end + 1s"
          attributeName="x" from="500" to="100" dur="3s" fill="freeze"></animate>
    <animate id="toYellow" attributeType="XML" attributeName="fill" 
          begin="0; toRed.end + 1s" 
          from="red" to="yellow" dur="3s" fill="freeze"></animate>
    <animate id="toRed" attributeType="XML" attributeName="fill" 
          begin="toYellow.end + 1s"
          from="yellow" to="red" dur="3s" fill="freeze"></animate>
    

    7.2.3 变换动画 <animateTransform>

    transform
    <animateMotion xlink:href="url(#rect1)"
      path="M 0 0 h 100 v 100 h -100 v -100 z"
      rotate="auto"
      dur="3s">
    </animateMotion>
    
    <svg viewBox="-400 -400 800 800">
      <rect x="-25" y="-25" width="50" height="50" fill="rgba(0,255,255,.6)">
        <animateMotion path="M 0 0 L 100 100 A 200 200 0 1 0 0 -100" dur="3s" rotate="auto" fill="freeze"></animateMotion>
      </rect>
      <path id="motion-path" d="M 0 0 L 100 100 A 200 200 0 1 0 0 -100" fill="none" stroke="gray"></path>
    
    <animateMotion dur="3s"  rotate="auto">
      <mpath xlink:href="#motion-path"></mpath>
    </animateMotion>
    

    7.3 脚本动画 ScriptingAnimation

    先看实例:SVG Scripting Example

    <svg width="500" height="100">
        <rect id="rect1" x="10" y="10" width="50" height="80"
              style="stroke:#000000; fill:none;"/>
    <input id="button1" type="button" value="Change Dimensions"
              onclick="changeDimensions()"/>
    <script>
        function changeDimensions() {
            document.getElementById("rect1").setAttribute("width", "100");
    </script>
    

    点击按钮,矩形会的宽度会增加到100,在线查看效果

    通过ID获取对SVG元素的引用,更改属性值:setAttribute()
    var svgElement = document.getElementById("rect1");
    svgElement.setAttribute("width","100")
    
    也可以通过getAttribute()获取属性的值:
    var svgElement = document.getElementById("rect1");
    var width = svgElement.getAttribute("width");
    
    您可以通过元素的style属性引用给定的CSS属性来更改SVG元素的CSS属性。
    var svgElement = document.getElementById("rect1");
    svgElement.style.stroke = "#ff0000";
    
    你也可以设置CSS属性只需要把元素名字写在svgElement.style.后面就可以了
    var setElement = document.getElementById("rect1")
    var stroke = svgElement.style.stroke;
    

    上面段代码会读取stroke的值。
    如果CSS属性名字包含破折号,比如:stroke-width,就需要用[""]包起来,这样做是因为带有短划线的属性名称在JavaScript中无效。
    例如,你不能这样写element.style.stroke-width,而是要写成:element.style['stroke-width']

    如果需要,您可以直接在SVG中将事件侦听器添加到SVG形状。 你这样做就像使用HTML元素一样。 以下是添加onmouseover和onmouseout事件侦听器的示例:

    <rect x="10" y="10" width="100" height="75"
          style="stroke: #000000; fill: #eeeeee;"
          onmouseover="this.style.stroke = '#ff0000'; this.style['stroke-width'] = 5;"
           onmouseout="this.style.stroke = '#000000'; this.style['stroke-width'] = 1;" />    
    

    你还可以使用addEventListener()函数方法:

    var svgElement = document.getElementById("rect1");
    svgElement.addEventListener("mouseover", mouseOver);
    function mouseOver() {
        alert("event fired!");
    

    本示例将一个名为mouseOver的事件侦听器函数添加到mouseover事件。 这意味着,只要用户将鼠标悬停在SVG元素上,就会调用事件侦听器函数。

    动画的暂停与启动

    为了动画SVG形状,您需要重复调用JavaScript函数。 该功能改变形状的位置或尺寸。 当函数被重复调用并且间隔非常短时,形状的位置或尺寸也会以非常短的时间间隔更新,这使得形状呈现动画效果。

    这里是一个SVG脚本动画的例子。 示例下面显示了创建它的代码。 点击SVG图像下面的两个按钮来启动和停止动画。

    <svg width="500" height="100">
        <circle id="circle1" cx="20" cy="20" r="10"
                style="stroke: none; fill: #ff0000;"/>
    <script>
        var timerFunction = null;
        function startAnimation() {
            if(timerFunction == null) {
                timerFunction = setInterval(animate, 20);
        function stopAnimation() {
            if(timerFunction != null){
                clearInterval(timerFunction);
                timerFunction = null;
        function animate() {
            var circle = document.getElementById("circle1");
            var x = circle.getAttribute("cx");
            var newX = 2 + parseInt(x);
            if(newX > 500) {
                newX = 20;
            circle.setAttribute("cx", newX);
    </script>
    <input type="button" value="Start Animation" onclick="startAnimation();">
    <input type="button" value="Stop Animation" onclick="stopAnimation();">
    两个HTML按钮都附有一个onclick监听器。 这些监听器调用启动和停止动画的startAnimation()和stopAnimation()函数。 动画是通过设置一个每20毫秒调用一次animate()函数的计时器来启动的。 通过再次清除该定时器功能停止动画。

    动画是在animate()函数内执行的。 首先,函数通过document.getElementById()函数获取对SVG图像中<circle>元素的引用。 然后读取该圆圈的cx属性并将其转换为数字。 然后将2添加到cx值。 如果新的x值大于500,则重置为20.最后,将新的x值放回到<circle>元素的cx属性中。 这个圆被移动到一个新的x位置。

    利用JS创建动画

    requestAnimationFrame(update)
    

    示例 力导向图