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标签

<p>
    <svg>
        ...
    </svg>
</p>
  • 1.1.4 作为CSS背景

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



[2]

1.2 基本图形和属性

  • 基本图形

<rect>
<circle>
<ellipse>
<line>
<polyline>
<polygon>

  • 基本属性

fill
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 ....


1.2.1 <rect>

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

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


1.2.2 <circle>

<circle cx="100" cy="100" r="50" fill="red" />

cx/cy表示圆心的位置


1.2.3 <ellipse>

<ellipse cx="100" cy="100" rx="80" ry="40" fill="red"/>


1.2.4 <line>

<line x1="100" y1="200" x2="400" y2="100" style="stroke:red" />


1.2.5 <polyline>

<polyline points="50 200 200 50 400 200 200 400" fill="none" stroke="red" />


1.2.6 <polygon>

<polygon points="50 200 200 50 400 200 200 400"fill="none" stroke="red" />


1.2.7 填充、描边和变形

<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>

[3]

1.3基本操作API

  • 创建图形
document.createElementNS(ns,tagName)
  • 添加图形
element.appendChild(childElement)
  • 设置/获取属性
element.setAttribute(name,value)
element.getAttribute(name)

[4]

综合实例:简单的SVG编辑器

点击这里查看源代码

[5]

二、SVG中的坐标系统与坐标变换

[6]

2.1 SVG的世界、视野、视窗的概念

  • 世界是无穷大的
  • 视野就是观察世界的一个矩形区域


  • width,height - 控制视窗
  • SVG代码 - 定义世界
  • viewBox,preserveAspectRadtio - 控制视野
    查看完整代码
<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>

[7]

2.2 SVG中的图形分组

  • <g>标签来创建分组
  • 属性继承
  • tranform属性定义坐标变换
  • 可以嵌套使用
<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>
    </g>
</svg>
整体位移

[8]

2.3 坐标系统概述

  • 笛卡尔直角坐标系
  • 原点
  • 互相垂直的两条数轴
  • 角度定义


    角度是顺时针

[9]

2.4 四个坐标系

  • 2.4.1用户坐标系(User Coordinate)
    世界的坐标系--原始坐标系

  • 2.4.2自身坐标系(Current Coordinate)
    每个图形元素或分组独立与生俱来

  • 2.4.3前驱坐标系(Previous Coordinate)
    父容器的坐标系
    Ouser就是前驱坐标系
    Oa就是自身坐标系


C、D的前驱坐标系:OB,重合是因为C、D没有变化(translate)
C的自身坐标系是Oc

  • 2.4.4参考坐标系(Reference Coordinate)
    使用其他坐标系来考究自身的情况时使用

    相对世界坐标系Ouser时,矩形的坐标就是(50,50),此时Ouser就是参考坐标系

[10]

2.5 坐标变换

  • 2.5.1 定义
    -数学上,坐标变换是采用一定的数学方法将一个坐标系的坐标变换为另一个坐标系的坐标过程。
    -SVG中坐标变换是对一个坐标系到另一个坐标系的变换的描述

  • 2.5.2 线性变换

  • 2.5.3 线性变换列表
后面的变换乘在后面和前面效果会不一样
  • 2.5.4 transform属性
    -前驱坐标系:父容器的坐标系
    -transform属性:定义前驱坐标系到自身坐标系的线性变换
    -语法:
rotate(<deg>)*
translate(<x>,<y>)*
scale(<sx>,<sy>)*
matrix(<a>,<b>,<c>,<d>,<e>,<f>)*

实例:查看原代码

<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="600" viewBox="-200.5 -100.5 1000 600">
        <defs>
            <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>
            </g>
        </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>
            </g>

            <g id="d" stroke="orange" fill="orange" transform="translate(150, 150)">
                <text x="5" y="20">d</text>
                <use xlink:href="#coord"></use>
            </g>
        </g>
    </svg>
transform



[11]

三、颜色、渐变和笔刷

[12]

3.1 SVG-RGB和HSL

  • 都是CSS3支持的颜色表示方法

3.1.1 RGB

  • 表示方式:rgb(r,g,b)或#rrggbb
  • 优势:显示器容易解析
  • 劣势:不符合描述颜色的习惯


3.1.2 HSL

  • 三个分量分别表示颜色、饱和度、亮度
  • 格式:hsl(h,s%,l%)
  • 取值范围:
    h: [0,359]
    s, l : [0,100]


3.1.2 透明度

  • rgba(r,g,b,a)和hsla(h,s%,l%,a)表示带透明度的颜色
  • opacity属性表示元素的透明度
  • a和opacity的取值范围: [0,1]


3.1.4 在SVG中应用颜色

<rect fill="rgb(255,0,0)" opacity="0.5">
<rect stroke="hsla(0,50%,60%,0.5)">
  • 互相转换的原理

[13]

3.2 线性渐变和径向渐变

3.2.1 线性渐变:

  • <linerGradient>和<stop>
  • 定义方向
  • 关键点位置及颜色
  • gradientUnits
<svg xmlns="http://www.w3.org/2000/svg">
    <defs>
        <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>

3.2.2 径向渐变:

  • <linerGradient>和<stop>
  • 定义方向
  • 关键点位置及颜色
  • gradientUnits
  • 焦点位置
<svg xmlns="http://www.w3.org/2000/svg">
    <defs>
        <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" />
</svg>

[14]

3.3 使用笔刷

  • 绘制纹理
  • <pattern>标签
  • patternUnits和patternContentUnits
    pattern 的属性
    patternUnits:
    objectBoundingBox : (默认)为容器百分比
    userSpaceOnUse : width 和 height 以世界坐标系为准,为宽度、高度
    patternContentUnits:
    userSpaceOnUse : (默认)为以世界坐标系为准
    objectBoundingBox : pattern 的子元素(这里指 circle 和 polygon,尺寸属性为 rect 的百分比)
    一般情况下 patternContentUnits 为 objectBoundingBox 时,patternUnits 也为 objectBoundingBox,好处理
<svg xmlns="http://www.w3.org/2000/svg">
    <defs>
        <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>
</svg>
<pattern id="p1" x="0" y="0" width="0.2" height="0.2" patternUnits="userSpaceOnUse">   

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

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

[15]

四、Path高级教程

[16]

4.1 Path概述

<path d="M0,0L10,20C30-10,40,20,100,100" stroke="red">
<tiger.svg>

  • 以下path字符串都是一样的

<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 无差别,因为表示闭合,其后不用跟坐标。
命令 含义
M/m (x,y)+ 移动当前位置到(x, y) (小写表示相对于上个坐标的位移, 下同)
L/l (x,y)+ 画一条直线到(x, y)
H/h (x)+ 水平画一条直线到 x
V/v (y)+ 竖直画一条直线到 y
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表明弧线顺时间旋转. 具体解释看如何绘制椭圆弧
  • path命令基本规律:
  • 区分大小写:大写表示坐标参数为绝对位置,值决定位置;小写则为相对位置,值决定长度
  • 最后的参数表示最终要到达的位置
  • 上一个命令结束的位置就是下一个命令开始的位置
  • 命令可以重置参数表示重复执行同一条命令

[17]

4.2 移动和直线命令

  • M (x,y)+ 移动画笔,后面如果有重复参数,会当做是L命令处理
  • L (x,y)+ 绘制直线到指定位置
  • H (x)+ 绘制水平线到指定的 X 位置
  • V (y)+ 绘制竖线到指定的 Y 位置
  • m、l、h、v使用相对位置绘制,值决定线的长度
    例:
M 200 200 h 300 v100 l 100 -100 M 0 0 L 200 200
M 200 200 h 300 v100 l 100 -100 M 0 0 L 200 200

[18]

4.3 弧线命令

A(rx,ry,xr,laf,sf,x,y) - 绘制弧线

最复杂的命令:

  • rx - (radius-x)弧线所在椭圆的X半轴长
  • 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 - 弧的终点位置
x-axis-rotation=30
M 200 200 A 200 100 216 1 1 300 300
M 200 200 h 100 l -100 100 v -100 M 300 200 A 100 100 0 0 1 200 300

[19]

4.4 贝塞尔曲线命令

点击查看贝兹曲线

直线的轨迹

二次贝塞尔曲线
三次贝塞尔曲线
四次贝塞尔曲线


4.4.1 二次贝塞尔曲线命令

  • 起始点
  • 结束点
  • 控制点
  • 控制线
M x0 y0 Q x1 y1 x y


4.4.2 三次贝塞尔曲线命令

  • 起始点
  • 结束点
  • 控制点
  • 控制线
M x0 y0 C x1 y1 x2 y2 x y
http://myst729.github.io/bezier-curve/
关于三次贝塞尔曲线的例子


4.4.3 光滑曲线

  • T: Q的光滑版本
    C1是上一段曲线的控制点关于当前去先期试点的镜像位置
  • S: C的简化版本
    C1是上一段曲线的控制点2关于当前曲线起始点的镜像位置

M 100 200 C 100 100 250 100 250 200 S 400 300 400 200
S 400 300 400 200 代替了 C 250 300 400 300 400 200


[20]

4.5 回顾和思考

  • Path命令的作用是什么,Path字符串的格式是什么?
  • 一共有多少个Path命令,它们分别得参数是什么?
  • 如何求贝塞尔曲线的长度,如何球整个Path的长度
  • 如何求一个Path的子路径?
  • 如何求两个Path的补间?
上面的C的高度为什么是100?圆的半径为75,事实证明三次贝塞尔曲线画出来的也并非是一个标准圆



[21]

五、SVG文本

[22]

5.1 <text>和<tspan>创建文本

  • x和y属性 - 定位标准
  • dx和dy属性 - 字形偏移
  • style属性 - 设置样式

SVG 画网格

<svg xmlns="http://www.w3.org/2000/svg">
    <defs>
        <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>
</svg>
<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>     //辅助线
dx="20 40 60 80 100" dy="20 40 60 80 100"

实例,使用 正弦曲线 让文字动起来

<!DOCTYPE html>
<html>
<head>
<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>
<body>
<!-- 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>
</svg>
<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>
<tspan>
  • dy属性在tspan上设置之后,tspan的属性会传递给后面,并且text上的dx、dy就会被覆盖 而且,。

[23]

5.2 垂直居中问题

  • text-anchor - 水平居中属性
  • dominant-baseline属性
  • 模拟居中
    源代码

垂直水平居中

查看效果

[24]

5.3 <textPath>让文本在指定路径上排列

  • 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 布局原理

    渲染原理

  • 5.3.3 定位属性x,y,dx,dy的作用

  • x、text-anchor和startOffset属性
    确定排列起始位置
<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>
</svg>
  • dx、dy属性
    切线和法线方向的偏移
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>
</svg>
  • 5.3.4 脚本控制
  • setAttributeNS()方法设置 xlink:href属性
  • 把文本节点替换为<textpath>
    源代码
    查看演示

注意:超出路径长度,不会被渲染

[25]

5.4 <a>插入超链接

  • 可以添加到任意的图形上
  • xlink:href 指定链接地址
  • xlink:title 指定连接提示
  • 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>
    </a>
</svg>

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




[26]

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

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

用法

xlink:href="#id"

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

[27]

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>

[28]

6.3 <mask> 标签创建蒙版

mask="url(#mask-id)"

<g id="reflact" transform="translate(0 100)" mask="url(#fading)">
  <!-- 绘制线性渐变 -->
  <defs>
    <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)" />
</g>

查看源文件



[29]

七、SVG动画

7.1 动画原理

image.png



[30]

7.2 SMIL for SVG


7.2.1 定位动画目标

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



[31]

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>
</svg>

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

<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>



[32]

7.2.3 变换动画 <animateTransform>

transform 描述
translate(x,y) 平移:将用户坐标系统的坐标原点移动到 (x, y)
scale(xFactor, yFactor) 缩放:将用户坐标系统的xy轴单位长度分别乘 (xFactor, yFactor)倍
scale(factor) 缩放:同 scale(factor, factor)
rotate(angle,centerX,centerY) 旋转:将用户坐标系统以 (centerX, centerY) 为旋转中心顺时针旋转 angle 度
rotate(angle) 旋转:同 rotate(angle, 0, 0)
skewX(angle) 倾斜:根据angle倾斜所有 x 轴坐标,视觉上会看到 y 轴倾斜
skewY(angle) 倾斜:根据angle倾斜所有 y 轴坐标,视觉上会看到 x 轴倾斜
matrix(a b c d e f) 矩阵变换:将坐标系统进行矩阵变换
  • 设置要进行动画的属性以及变化范围、时间长度
<animateTransform xlink:href="url(#rect1)"
  attributeName="transform"
  attributeType="XML"
  type="translate"
  from="0 0"
  to="100 100"
  dur="3s">
</animateTransform>
<animateTransform 
  attributeName="transform"
  attributeType="XML"
  type="scale"
  from="1"
  to="3"
  dur="3s"
  fill="freeze">
</animateTransform>



[33]

7.2.4 轨迹移动 <animateMotion>

  • 设置轨迹路径
<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>
</svg>
<animateMotion dur="3s"  rotate="auto">
  <mpath xlink:href="#motion-path"></mpath>
</animateMotion>




[34]

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;"/>
</svg>
<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;"/>
</svg>

<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>
<br/>
<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)
  • 示例 力导向图


查看完整代码




目录


  1. 一、SVG基本概念
     1.1SVG的使用方式

  2.  1.2 基本图形和属性

  3.  1.3基本操作API

  4.  综合实例:简单的SVG编辑器

  5. 二、SVG中的坐标系统与坐标变换

  6.  2.1 SVG的世界、视野、视窗的概念

  7.  2.2 SVG中的图形分组

  8.  2.3 坐标系统概述

  9.  2.4 四个坐标系

  10.  2.5 坐标变换

  11. 三、颜色、渐变和笔刷

  12.  3.1 SVG-RGB和HSL

  13.  3.2 线性渐变和径向渐变

  14.  3.3 使用笔刷

  15. 四、Path高级教程

  16.  4.1 Path概述

  17.  4.2 移动和直线命令

  18.  4.3 弧线命令

  19.  4.4 贝塞尔曲线命令

  20.  4.5 回顾和思考

  21. 五、SVG文本

  22.  5.1 <text>和<tspan>创建文本

  23.  5.2 垂直居中问题

  24.  5.3 <textPath>让文本在指定路径上排列

  25.  5.4 <a>插入超链接

  26. 六、图形引用、裁切和蒙版
     6.1 <use>标签创建图形引用

  27.  6.2 <cilp>标签裁切图形

  28.  6.3 <mask> 标签创建蒙版

  29. 七、SVG动画

  30.  7.2 SMIL for SVG

  31.   7.2.2 基本动画<animate>

  32.   7.2.3 变换动画 <animateTransform>

  33.   7.2.4 轨迹移动 <animateMotion>

  34.  7.3 脚本动画 ScriptingAnimation

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260