可以用于制作SVG路径动画的JavaScript库有很多,本文将为大家介绍如何使用Snap.svg动画库来制作效果非常酷的SVG路径动画效果。
先来一张GIF格式的SVG路径动画预览图看看效果!
SVG和SnapSVG动画库介绍
SVG是可缩放矢量图形(stands for Scalable Vector Graphics)。SVG基于XML格式来定义矢量图,它支持二维的矢量图格式,并且可以交互和制作动画效果。所有的现代浏览器都支持SVG格式。
作为矢量图格式,SVG常用于制作以下一些图形:
- 二维的矢量图。
- 线性图表,饼状图表等。
- 桌面、平板电脑、手机和APP应用中的可缩放图标和logo。
- 建筑与设计图。
SnapSVG是一款基于JavaScript的动画库,它可以非常轻松的实现一些SVG的交互动画效果。
其它还有一些类似的SVG动画库,如raphaeljs、bonsaijs和velocityjs等。
制作SVG路径动画
关于示例中的SVG矢量图是直接从illustrator中导出的,在压缩包中有该矢量图的源文件,你使用Save as选项就可以直接将它导出为SVG格式。另外需要注意的是宇宙飞船的SVG矢量图是单独进行导出的。
下面开始来制作小宇宙飞船的路径动画。首先我们需要绘制一条动画的路径。代码如下:
flight_path = map.path('M339.233,312.53c-37.779, 16.943-119.567-21.598-134.165-71.924c-19.086-65.802, 19.072-124.856,64.665-145.753s157.388-22.525,219.128, 74.23s-20.242,229.959-114.73, 240.688c-88.678,10.069-230.255-62.044-230.25-163.305') .attr({ 'fill': 'none', 'stroke': 'none'});
关于SVG路径的更多信息可以参考这里。在上面的代码中是使用SnapSVG的path()
方法来直接生成一条路径。
为了制作路径动画,我们需要知道路径的长度。我们可以通过Snap.path.getTotalLength(path)
方法来获取。
flight_path_length = Snap.path.getTotalLength(flight_path);
SnapSVG为我们提供了1个用于动画的方法:
Snap.animate(from, to, setter, duration, [easing], [callback])
from
:是动画的开始点,通常为0,0表示从路径的开始位置开始动画。to
:是动画的结束点,它等于路径的长度。setter
:是一个在动画中每一步都被调用的函数。Setter
中传入一个称为step
的整数参数。我们将使用这个参数来计算和动画元素的位置。callback
:是动画结束之后的回调函数。我们可以使用这个函数来制作进一步的飞船动画。
需要注意的是,Snap.animate()
是一个用于动画两个数值的通用函数,而不是直接动画元素的函数。
我们已经知道了SVG路径的长度,所以我们可以开始使用Snap.animate()
函数来制作动画了,代码如下:
Snap.animate(0, flight_path_length, function(step){ //这里编写位置的代码 }, 5000, function(){ //这里是回调函数 });
重点是要看setter
函数该如何编写。setter
函数接收一个step
参数,我们将使用step
参数来获取通过Snap.path.getPointAtLength(flight_path, step)
方法得到的指定的点,并使宇宙飞船沿这些点进行动画。
Snap.animate()
函数的最终代码应该像下面这样:
Snap.animate(0, flight_path_length, function( step ) { moveToPoint = Snap.path.getPointAtLength( flight_path, step ); x = moveToPoint.x - (spaceshipbbox.width/2); y = moveToPoint.y - (spaceshipbbox.height/2); spaceship.transform('translate(' + x + ',' + y + ') rotate('+ (moveToPoint.alpha - 90)+', '+spaceshipbbox.cx+', '+spaceshipbbox.cy+')'); },5000, mina.easeout ,function(){ ship_move_up(); });
其它动画代码
在DEMO中还有另外2个小动画效果。小火箭的推进器是一个无限循环的上下运动动画,还有就是在路径动画结束时,小火箭的上下运动动画效果。这两个动画都是上下运动的动画,我们使用transform(x,y)
属性来制作这两个动画效果。
整个SVG路径动画的完整代码如下:
var paper, map, spaceship, thruster, moon, flight_path, flight_path_length, last_point; window.onload = function () { paper = map; map = Snap('#svg-doc'); spaceship = map.select('#spaceship'); spaceshipbbox = spaceship.getBBox(); thruster = map.select('#thruster'); moon = map.select('#moon'); flight_path = map.path('M339.233,312.53c-37.779,16.943-119.567-21.598-134.165-71.924c-19.086-65.802,19.072-124.856,64.665-145.753s157.388-22.525,219.128,74.23s-20.242,229.959-114.73,240.688 c-88.678,10.069-230.255-62.044-230.25-163.305').attr({ 'fill': 'none', 'stroke': 'none'}); flight_path_length = Snap.path.getTotalLength(flight_path); last_point = flight_path.getPointAtLength(flight_path_length); // starting the thruster animation animate_thruster_down(); Snap.animate(0, flight_path_length, function( step ) { moveToPoint = Snap.path.getPointAtLength( flight_path, step ); x = moveToPoint.x - (spaceshipbbox.width/2); y = moveToPoint.y - (spaceshipbbox.height/2); spaceship.transform('translate(' + x + ',' + y + ') rotate('+ (moveToPoint.alpha - 90)+', '+spaceshipbbox.cx+', '+spaceshipbbox.cy+')'); },5000, mina.easeout ,function(){ ship_move_up(); }); }; function ship_move_up(){ spaceship.animate({'transform': 'translate(' + (last_point.x - (spaceshipbbox.width/2)) + ',' + (last_point.y - (spaceshipbbox.height / 2) - 20) + ')'},1300, function(){ ship_move_down(); }); } function ship_move_down(){ spaceship.animate({'transform': 'translate(' + (last_point.x - (spaceshipbbox.width/2)) + ',' + (last_point.y - (spaceshipbbox.height / 2)) + ')'},1100, function(){ ship_move_up(); }); } function animate_thruster_up(){ thruster.animate({'transform': 'translate(0,-5)'},100, function(){ animate_thruster_down(); }); } function animate_thruster_down(){ thruster.animate({'transform': 'translate(0,0)'},100, function(){ animate_thruster_up(); }); }