SVG支持动画。可以通过以下几种方法获得动画效果:
一、SVG中的动画元素
SVG中的动画元素有五个,它们都可以随着时间的变化而改变SVG元素的属性或样式值,如下所示:
沿着某路径移动SVG元素获得动画效果, 该元素提供一种通过指定路径移动元素的简单方法。路径数据与路径元素的 d 属性相同,但用路径元素指定。也可以用 xlink:href 将它链接到 animateMotion 元素。起点和终点由 from 和 to 属性确定,并且可以通过将 rotate 值设为 auto 来设置对象垂直对齐于路径。(也可以将 rotate 属性设为 auto-reverse 以将这个方位改变 180 度。或者可以给定一个特定角度)。如动画和交互性所示: <animateMotion path="M0,300 S150,100 200,200 S400,400 500,0" dur="8s" repeatCount="indefinite" rotate="auto" />
<circle cx="250" cy="100" r="50" fill="red"> <animateColor attributeType="CSS" attributeName="fill" from="rgb(255,0,0)" to="rgb(0,0,255)" dur="8s" repeatCount="indefinite"/> </circle>
<rect x="333" y="49" width="50" height="50" fill="none" stroke="purple"> <animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="3" additive="sum" begin="3s" dur="6s" fill="freeze" /> <animateTransform attributeName="transform" attributeType="XML" type="translate" from="0,0" to="-222,-45" additive="sum" begin="3s" dur="6s" fill="freeze" /> </rect>
<circle cx="250" cy="100" r="50" fill="red"> <set attributeName="r" to="100" begin="1s" dur="5s" fill="remove" /> </circle>
attributeName="<attributeName>":批明所作用的SVG元素中哪个属性或样式需要产生动画效果。
attrbuteType="<XML|CSS|auto>":指明产生动画效果的属性或样式值是哪个命名空间定义的。“XML”表示“attributeName”的值是默认XML命名空间里定义的XML属性名;“CSS”表示“attributeName”的值是默认CSS属性的名称;“auto”是默认值,解析器解析时先在CSS属性列表中查找是否有匹配“attributeName”的属性名,然后再在XML的命名空间里找
1.与时间控制相关的常用属性
begin="<clock-time-value>|wallclock-sync-value|indefinite|eventName":定义动画的开始时刻。
2.与过程控制相关的常用属性
from="<value>":定义该动画元素所作用的属性值在开始变化时的值
to="<value>":定义该动画元素所作用的属性值在结束变化时的值
by="<value>":定义该动画元素所作用的属性值每次变化的步长值
calcMode="discrete|linear|paced|spline":定义动画关键点直接过渡的插值计算方式
例子1:
<rect x="50" y="50" width="100" height="50"> <animate attributeType="XML" attributeName="x" from="50" to="300" dur="3s" begin="3s" restart="always" repeatCount="3" > </animate> </rect>
例子2:
<text x="0" y="0" font-size="37" visibility='hidden" stroke="black" stroke-width="2" > <animateMotion path="M0,0 L50,50 L100,150" begin="1s" dur="5s" fill="freeze" rotate="auto"/> </text>
例子3:
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> <g transform="translate(100,100)"> <text id="TextElement" x="0" y="0" style="font-family:Verdana;font-size:24; visibility:hidden"> It's SVG! <set attributeName="visibility" attributeType="CSS" to="visible" begin="1s" dur="5s" fill="freeze" /> <animateMotion path="M 50 50 L 300 300" begin="1s" dur="5s" fill="freeze" /> <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="360" begin="1s" dur="15s" fill="freeze" repeatCount='indefinite'/> <animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="3" additive="sum" begin="1s" dur="5s" fill="freeze" /> </text> </g> </svg>
二、事件的脚本编制(DOM动画)
象 HTML 页面一样,可以设置 SVG 图像以捕获某些事件(如点击鼠标和滚动),并用它们启动脚本。在构建简单SVG 图像时,可以通过属性捕获这些事件。最常用的是onclick、onactivate、onmousedown、onmouseup、onmouseover、onmousemove、onmouseout、onload、onresize、onunload 和 onrepeat。
当这些事件之一被触发,就可以将事件对象本身提供给脚本,脚本反过来再用它确定哪个对象触发了该事件(也就是点击了什么对象)。然后脚本可以操纵那个对象的特性,如它的属性。
这一示例回到了图案示例,但在此例中,当用户点击椭圆时,其填充由白色变为使用图案。
<?xml version="1.0"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="500" height="300" xmlns="http://www.w3.org/2000/svg"> <desc>Scripting the onclick event</desc> <script type="text/ecmascript"> <![CDATA[ function hideReveal(evt) { var imageTarget = evt.target; var theFill = imageTarget.getAttribute("fill"); if (theFill == 'white') imageTarget.setAttribute("fill", "url(#notes)"); else imageTarget.setAttribute("fill", "white"); } ]]> </script> <defs> <pattern id="notes" x="0" y="0" width="50" height="75" patternTransform="rotate(15)" patternUnits="userSpaceOnUse"> <ellipse cx="10" cy="30" rx="10" ry="5"/> <line x1="20" y1="30" x2="20" y2="0" stroke-width="3" stroke="black"/> <line x1="20" y1="0" x2="30" y2="5" stroke-width="3" stroke="black"/> </pattern> </defs> <!-- Outline the drawing area with a blue line --> <rect x="1" y="1" width="350" height="200" fill="none" stroke="blue"/> <ellipse onclick="hideReveal(evt)" cx="175" cy="100" rx="125" ry="60" fill="url(#notes)" stroke="black" stroke-width="5"/> </svg>
三、基本的声明性 (SMIL) 动画
<?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="800px" height="800px" viewBox="0 0 800 800" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <!-- Note that this is required in order to use xlink in the <use> element. --> <!-- THIS EXAMPLE NOT SUPPORTED IN INTERNET EXPLORER --> <title>Simplest SVG Animation</title> <desc>SVG declarative animation is used to rotate a square.</desc> <!-- Create a Cartesian coordinate system (with the y-axis flipped) for the animated square. That is, place the origin at the center of the 800 x 800 SVG viewport. --> <g transform="translate(400, 400)"> <!-- A 200 x 200 square with the upper left-hand corner at (-100, -100). This places the center of the square at the origin (0, 0): --> <rect x="-100" y="-100" width="200" height="200" rx="5" ry="5" style=" fill: orange; stroke: black; stroke-width: 3; stroke-dasharray: 10, 5;"> <animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0" to="90" begin="0" dur="5s" fill="freeze" /> </rect> <line x1="-400" y1="0" x2="400" y2="0" style="stroke: black;" /> <!-- Represents the x-axis. --> <line x1="0" y1="-400" x2="0" y2="400" style="stroke: black;" /> <!-- Represents the y-axis (although up is negative and down is positive). --> </g> </svg>
同样的效果用javascript来实现:
<!DOCTYPE html> <html> <head> <title>JavaScript SVG Animation</title> <meta http-equiv="X-UA-Compatible" content="IE=Edge"/> <!-- Remove this line in production. --> </head> <body> <svg width="800px" height="800px" viewBox="0 0 800 800"> <g transform="translate(400, 400)"> <!-- Create a Cartesian coordinate system (with the y-axis flipped) for the animated square. That is, place the origin at the center of the 800 x 800 SVG viewport: --> <!-- A 200 x 200 square with the upper left-hand corner at (-100, -100). This places the center of the square at the origin (0, 0): --> <rect id="mySquare" x="-100" y="-100" width="200" height="200" rx="5" ry="5" style=" fill: orange; stroke: black; stroke-width: 3; stroke-dasharray: 10, 5;" /> <!-- Represents the x-axis: --> <line x1="-400" y1="0" x2="400" y2="0" style="stroke: black;" /> <!-- Represents the y-axis (although up is negative and down is positive): --> <line x1="0" y1="-400" x2="0" y2="400" style="stroke: black;" /> </g> </svg> <script> "use strict"; /* CONSTANTS */ var initialTheta = 0; // The initial rotation angle, in degrees. var thetaDelta = 0.3; // The amount to rotate the square about every 16.7 milliseconds, in degrees. var angularLimit = 90; // The maximum number of degrees to rotate the square. var theSquare = document.getElementById("mySquare"); theSquare.currentTheta = initialTheta; // The initial rotation angle to use when the animation starts, stored in a custom property. var requestAnimationFrameID = requestAnimationFrame(doAnim); // Start the loop. function doAnim() { if (theSquare.currentTheta > angularLimit) { cancelAnimationFrame(requestAnimationFrameID); // The square has rotated enough, instruct the browser to stop calling the doAnim() function. return; // No point in continuing, bail now. } theSquare.setAttribute("transform", "rotate(" + theSquare.currentTheta + ")"); // Rotate the square by a small amount. theSquare.currentTheta += thetaDelta; // Increase the angle that the square will be rotated to, by a small amount. requestAnimationFrameID = requestAnimationFrame(doAnim); // Call the doAnim() function about 60 times per second (60 FPS), or about once every 16.7 milliseconds until cancelAnimationFrame() is called. } </script> </body> </html>
用SVGDOM来实现:
<!DOCTYPE html> <html> <head> <title>JavaScript SVG Animation</title> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <!-- Remove this line in production. --> </head> <body> <svg id="svgElement" width="800px" height="800px" viewBox="0 0 800 800"> <!-- Give the svg element a name so that we can easily access it via JavaScript. --> <g transform="translate(400, 400)"> <!-- Create a Cartesian coordinate system (with the y-axis flipped) for the animated square. That is, place the origin at the center of the 800 x 800 SVG viewport: --> <!-- A 200 x 200 square with the upper left-hand corner at (-100, -100). This places the center of the square at the origin (0, 0). Give the square a name so we can easily access it via JavaScript: --> <rect id="mySquare" x="-100" y="-100" width="200" height="200" rx="5" ry="5" style=" fill: orange; stroke: black; stroke-width: 3; stroke-dasharray: 10, 5;" /> <!-- Represents the x-axis: --> <line x1="-400" y1="0" x2="400" y2="0" style="stroke: black;" /> <!-- Represents the y-axis (although up is negative and down is positive): --> <line x1="0" y1="-400" x2="0" y2="400" style="stroke: black;" /> </g> </svg> <script> "use strict"; /* CONSTANTS */ var initialTheta = 0; // The initial rotation angle, in degrees. var thetaDelta = 0.3; // The amount to rotate the square about every 16.7 milliseconds, in degrees. var angularLimit = 90; // The maximum number of degrees to rotate the square. /* GLOBALS */ var requestAnimationFrameID; var mySquare = document.getElementById("mySquare"); var transformObject; mySquare.currentTheta = initialTheta; // The initial rotation angle to use when the animation starts, stored in a custom property. transformObject = svgElement.createSVGTransform(); // Create a generic SVG transform object so as to gain access to its methods and properties, such as setRotate(). mySquare.transform.baseVal.appendItem(transformObject); // Append the transform object to the square object, now the square object has inherited all the transform object's goodness. requestAnimationFrameID = requestAnimationFrame(doAnim); // Start the animation loop. function doAnim() { var transformObject; if (mySquare.currentTheta > angularLimit) { cancelAnimationFrame(requestAnimationFrameID); // Instruct the browser to stop calling requestAnimationFrame()'s callback. return; } mySquare.transform.baseVal.getItem(0).setRotate(mySquare.currentTheta, 0, 0); // Access the transform object (that was appended to mySquare in the init() function) and use its setRotate method to rotate the square about the point (0, 0) (which is at the center of the SVG viewport). mySquare.currentTheta += thetaDelta; // Place this line here so that the square isn't over rotated on the last call to doAnim(). requestAnimationFrameID = requestAnimationFrame(doAnim); // Call the doAnim() function about every 60 times per second (i.e., 60 FPS). } </script> </body> </html>
参考: