SVG采用的是使用文原本定义图形,这种文档结构很是适合于建立动画。要改变图形的位置、大小和颜色,只须要调整相应的属性就能够了。事实上,SVG有为各类事件处理而专门设计的属性,甚至不少仍是专门为动画量身定作的。在SVG中,实现动画一般使用SVG SMIL animation。
经过SMIL能够实现的基本动画:
•动画元素的数值属性(X, Y, …)
•动画属性变换(平移或旋转)
•动画颜色属性
•沿着运动路径运动(这一点很是有趣)css
对svg动画浏览器兼容状况:html
能够看到ie都不支持svg动画,移动端andriod4.1才开始支持svg动画。git
1. animate元素
这个是最基本的动画元素,能够直接为相关属性提供不一样时间点的值。
2. set元素
这个是animate元素的简写形式,支持全部的属性类型,尤为是当对非数字型的属性(例如visibility)进行动画时很方便。set元素是非增量的,相关的属性对之无效。 to指定的动画结束值类型必定要符合属性的取值类型。
3. animateMotion元素
路劲动画元素。github
4. animateColor元素
颜色动画元素。这是一个过期的元素,基本上全部功能均可以用animate代替,因此仍是不要用了。web
5. animateTransform元素
canvas
变换动画元素。看看特殊的一些属性:
type = "translate | scale | rotate | skewX | skewY"
这个属性指定了变换的类型,translate是默认值,这里的rotate是以svg容器的端点为圆心旋转。
from,by和to的值相应的都是对应变换的参数,这个仍是与前面讲的变换是一致的。values则是一组分号隔开的这样的值系列。浏览器
支持动画效果的元素和属性
基本上全部图形元素(path,rect,ellipse,text,image...),容器元素(svg, g, defs, use, switch, clipPath, mask...)都支持动画。基本上大多数的属性都支持动画效果。app
animate元素--基本元素动画svg
<svg width="200" height="200" > <rect x="0" y="40" width="200" height="200" fill="rgba(0,0,0,.4)" /> <text font-family="microsoft yahei" font-size="40" y="80" x="0" fill="red" stroke="green" stroke-width="1"> hello <animate attributeName="x" attributeType="XML" from="0" to="100" begin="0s" dur="2s" repeatCount="indefinite"/> </text> </svg>
set动画,能够方便设置延迟wordpress
<!-- set 能够实现基本的延迟功能 --> <svg width="200" height="200" > <rect x="0" y="40" width="200" height="200" fill="rgba(0,0,0,.4)" /> <text font-family="microsoft yahei" font-size="40" y="80" x="0" fill="red" stroke="green" stroke-width="1"> hello <set attributeName="x" attributeType="XML" to="80" begin="3s" /> </text> </svg>
animateMotion动画
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg"> <text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#cd0000">hello <animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" rotate="40" repeatCount="indefinite"/> </text> <path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" /> </svg>
animateTransform动画
<svg width="200" height="200" > <rect x="0" y="40" width="200" height="200" fill="rgba(0,0,0,.4)" /> <text font-family="microsoft yahei" font-size="40" y="80" x="0" fill="red" stroke="green" stroke-width="1"> hello <animate attributeName="x" attributeType="XML" from="0" to="100" begin="0s" dur="2s" repeatCount="indefinite"/> <animateTransform attributeName="transform" type="scale" from="1" to="1.2" begin="0s" dur="2s" repeatCount="indefinite"/> </text> </svg>
相关属性解释:
attributeName = <attributeName>
要变化的元素属性名称,① 能够是元素直接暴露的属性,例如,对于本文反复出现的「马」对应的text
元素上的x
, y
或者font-size
; ② 能够是CSS属性。例如,透明度opacity
.
attributeType = “CSS | XML | auto”
这个属性指定了属性取值的命名空间,这几个值的含义以下:
CSS:表明attributeName指定的属性是CSS属性。
XML:表明attributeName指定的属性是XML默认命名空间下的属性(注意svg文档本质上是xml文档)。
auto:表明先在CSS属性中查找attributeName指定的属性,若是没找到,则在默认的XML命名空间下寻找该属性。
注意:若是你不确信某属性是XML类别仍是CSS类别的时候,个人建议是不设置attributeType
值,直接让浏览器本身去判断
begin = "begin-value-list"
该属性定义了动画的开始时间。能够是分号分开的一系列时间值。也能够是一些其余触发动画开始的值。好比事件,快捷键等。
dur = Clock-value | "media" | "indefinite"
定义了动画的持续时间。能够设置为以时钟格式显示的值。也能够设置为下列两个值:
media:指定动画的时间为内部多媒体元素的持续时间。
indefinite:指定动画时间为无限。
repeatCount = numeric value | "indefinite"
设置了动画重复的次数。 indefinite表明无限重复。
repeatDur = Clock-value | "indefinite"
设置重复的总的动画时间。indefinite表明无限重复。
fill = "freeze" | "remove(默认值)"
设置了动画结束后元素的状态。freeze表示动画结束后元素停留在动画的最后状态。remove表明动画结束之后元素回到动画前的状态,这个是默认值。
1.利用stroke属性实现线框效果
在作这个动画以前,咱们先讲一下,作这个动画的stroke相关属性:
1. 若是不提供stroke属性,则默认不绘制图形边框。
2. 能够设置边的透明度,就是stroke-opacity,值的范围是0到1
3. 线的端点 - stroke-linecap属性,这个属性定义了线段端点的风格,这个属性可使用butt,square(方形),round(圆形)三个值
4.线的链接 - stroke-linejoin属性,定义了线段链接处的风格,这个属性可使用miter,round,bevel三个值
5. 线的虚实 - stroke-dasharray属性
这个属性是设置一些列数字,不过这些数字必须是逗号隔开的。属性中固然能够包含空格,可是空格不做为分隔符。每一个数字定义了实线段的长度,分别是按照绘制、不绘制这个顺序循环下去。
6.stroke-miterlimit:这个和canvas中的同样,它处理何时画和不画线链接处的miter效果。
7.stroke-dashoffset:这个属性设置开始画线的位置。
下面看看咱们如何实现效果:
html, body { background: #333; height: 100%; overflow: hidden; text-align: center; } .svg-wrapper { height: 60px; margin: 0 auto; position: relative; top: 50%; transform: translateY(-50%); width: 320px; } //初始咱们经过stroke-dasharray:140 540 即实线140 虚线540 可是总长度320*2+60*2=760 则说明最终能看到的实线为140
//而后经过stroke-dashoffset设置画线的位置 .shape { fill: transparent; stroke-dasharray: 140 540; stroke-dashoffset: -474; stroke-width: 8px; stroke: #19f6e8; } .text { color: #fff; font-family: 'Roboto Condensed'; font-size: 22px; letter-spacing: 8px; line-height: 32px; position: relative; top: -48px; } //经过animation切换便可 @keyframes draw { 0% { stroke-dasharray: 140 540; stroke-dashoffset: -474; stroke-width: 8px; } 100% { stroke-dasharray: 760; stroke-dashoffset: 0; stroke-width: 2px; } } .svg-wrapper:hover .shape { -webkit-animation: 0.5s draw linear forwards; animation: 0.5s draw linear forwards; } </style> <!-- SVG stroke-dasharray 属性 --> <div class="svg-wrapper"> <svg height="60" width="320" xmlns="http://www.w3.org/2000/svg"> <rect class="shape" height="60" width="320" /> </svg> <div class="text">HOVER</div> </div>
二.线条中心到两边扩张效果
两种方案:
第一种: css+svg实现
.path{ stroke-dasharray:0,200; stroke-dashoffset:-100; -webkit-animation: move 1s linear 0.5s forwards; animation: move 1s linear 0.5s forwards; } @-webkit-keyframes move{ 0%{ stroke-dasharray:0,200; stroke-dashoffset:-100; } 100%{ stroke-dasharray:200,0; stroke-dashoffset:0; } } <path class="path" d="M 10 75 L 200 75" stroke="red" stroke-linecap="round" stroke-width="1" fill="none"> </path>
第二种: svg实现
<svg width="200" height="200"> <path d="M 10 100 L 200 100" stroke="orange" stroke-linecap="round" stroke-width="1" stroke-dasharray="0,200" stroke-dashoffset="-100" fill="none"> <animate attributeName="stroke-dashoffset" attributeType="XML" from="-100" to="0" begin="0s" dur="1s" /> <!-- fill = "freeze" | "remove(默认值)" freeze表示动画结束后元素停留在动画的最后状态 remove表明动画结束之后元素回到动画前的状态,这个是默认值--> <animate attributeName="stroke-dasharray" attributeType="XML" from="0,200" to="200,0" begin="0s" dur="1s" fill="freeze"/> </path> </svg>
这里注意两个知识点:
fill = "freeze" | "remove(默认值)" freeze表示动画结束后元素停留在动画的最后状态 remove表明动画结束之后元素回到动画前的状态,这个是默认值
在直线上面stroke-dashoffset="100"和stroke-dashoffset="-100"在同一个位置,只是最终画的位置由stroke-dasharray="20 0"和stroke-dashoffset一块儿肯定,例前面两个值起始点120(100+20) 和80(|-100+20|)
三.填坑animateTransform中rotate针对的svg左上角那个点移动到元素中心点
实例代码:
<svg width="400" height="400"> <rect x="0" y="0" fill="green" rx="4" width="200" height="200"> <animateTransform attributeName="transform" type="rotate" form="0" to="360" begin="0" dur="5s" repeatCount="indefinite" /></rect> </svg>
例上面的代码咱们让200x200的方形元素,作旋转运动,可是在svg里面rotate旋转针对的点是svg的左上角。咱们想在针对元素中心点运动怎么办。
一般的解决方案:
<svg width="400" height="400"> <g transform="translate(200,200)"> <rect x="-100" y="-100" fill="green" rx="4" width="200" height="200"> <animateTransform attributeName="transform" type="rotate" form="0" to="360" begin="0" dur="5s" repeatCount="indefinite" /> <g> </svg>
咱们加了一个组合标签<g transform="translate(200,200)"></g>将svg的坐标起始点移动到容器的中心点(svg的占位位置仍是没有变化),而后元素再根据这个新的起始点画出来,进行旋转就能够了。
四.简单的用js操做动画的案例
<svg width="400" height="400"> <g transform="translate(200,200)"> <rect id="rect" x="-100" y="-100" fill="green" rx="4" width="200" height="200"> <!-- <animateTransform attributeName="transform" type="rotate" form="0" to="360" begin="0" dur="5s" repeatCount="indefinite" /> --> <g> </svg> <script> var cur = 0; var rect=document.getElementById("rect"); //requestAnimationFrame调用的频率是每秒60次逐帧动画 var frames = window.requestAnimationFrame(doAnim); function doAnim(){ if(cur>=360){ //取消帧动画 window.cancelAnimationFrame(frames); return; } cur++; console.log(cur); rect.setAttribute("transform", "rotate(" + cur + ")"); frames = window.requestAnimationFrame(doAnim); } </script>
参考资料:
突袭HTML5之SVG 2D入门(svg教程写的很全,推荐指数5星)
SVG 教程(w3school的svg教程,也不错)
mozilla svg教程(推荐给喜欢看英文教程的朋友)
知乎上面对svg的一些讨论(你们在使用时,有必要能够看一下)
推荐svg库: