本文主要演示了如何通过Snap.SVG创造一组栅格动画。
首先演示了如何用Snap.SVG创造元素, 然后说明了如何使设置元素的属性。 之后让一组元素平滑的进行动画, 最后使这组动画无限循环。
点击预览最终 Demo
目录
Snap.svg 是Adobe的一个开源JavaScript库, 用来更方便的控制SVG元素,就像用jQuery控制DOM元素一样。
在使用前,我们需要在官网上下载相对应的js文件。
这里只对功能做大致描述。 具体文档见 http://snapsvg.io/docs/
也可以查看 张鑫旭同学的中文文档
通过Snap.svg,我们可以Snap一个SVG元素:
var svg = Snap(width, height) ;
得到的svg元素则被Snap化了,使得我们更方便进行操控。 我们也可以像jQuery一样,直接选择一个SVG元素:
var svg = Snap("#svg-elem") ;
首先我们在页面的showSVG的div中创建一个SVG元素:
var showSVG = document.querySelector(".showSVG"); var svg = Snap(100, 100) ; showSVG.append(svg.node);
接下来我们就可以对其中的元素进行控制了。
添加一个元素, 比如 svg.paper.rect(x, y, h, w, [rx], [ry]):
var r1 = svg.paper.rect(0,0,20,100);
相当于在svg中插入一个rect:
返回一个snap元素。
更重要的是,我们可以对元素直接赋予动画, 这样就避免了书写复杂的SVG动画。
比如:
r1.animate({x:100},1000);
表示在1000ms的持续时间内, 将r1的x坐标移动到100。
Snap本身也有一个动画函数,可以更平滑的控制动画
Snap.animate(from, to, setter, duration, [easing], [callback]):
Snap.animate(0,100,function(val){ r1.attr({x:val}) }, 1000)
该动画效果类似上一个效果。 但是我们可以同时对多个元素和属性进行同步设置。
让一组元素平滑的进行动画,则需要我们对一组元素按顺序进行控制。
首先我们创建一组元素,代码如下
var g = svg.paper.g(); var c = Array.apply(null, {length: 20}) .map(Number.call, Number) .map(function(num){ var _t = svg.paper.rect((num-1)*10, 0, 9, 100).attr({fill:'#b00'}); g.add(_t); return _t; }); var s = g.selectAll('rect');
这里我们创建了一个包含20个元素的数组c, 里面每一个元素的x坐标分别增加10。
并将这些元素在SVG里面用Paper.g()进行分组。 最后将这些元素放到一个s的Snap.set里面,方便进行控制。
首先我们可以想到的,就是用 Snap.animate()
我们可以先添加元素到一个Snap.set组里面, 然后在进行动画时,在setter函数里逐个对set元素组里的的attr进行设置。
Snap.animate(0,100,function(val){ s.forEach(function(elem,i){ elem.attr({y : val/10+i*10}); }); },1000)
但是这样有几个弊端:
那么,我们想这样,对组里的每一个元素 分时段分别开始进行animate。
即类似以下伪代码:
for i in [i1,i2,i3] i animate wait 500 endfor
那么我们需要实现一个简单的 step_animate。
代码如下:
// animate by step // steps is the total number of step, // after init timeout // run step_func with each step. // call the callback after finished. function step_animate(init_timeout, steps, total_time, step_func, callback){ setTimeout(function(){ var intervalId = setInterval(step_func, total_time/steps); setTimeout(function(){ clearInterval(intervalId); if (callback != null) { callback(); } }, total_time); },init_timeout) }
注:不用Snap.animate进行step的设置,而是直接用setInterval, 因为Snap.animate有时运行会顿一下,然后Step就会出现间隔。
直接使用即可:
var k = 0; step_animate(0,20, 2000, function(){ c[k].animate({y:300},1500); c[k].animate({fill:'#3800BA'},1500); k++; })
测试代码,则可以看到可以运行了。
最后一个问题。 怎么让动画无限循环呢?
我们可以通过将step_animate函数包裹在一个Wrapper Function里面, 并在 callback里面递归调用Wrapper Function来实现:
function Anim() { var k = 0 ; s.attr({y:0}); s.attr({fill:'#c00'}); step_animate(0,20, 3000, function(){ c[k].animate({y:300},1500); c[k].animate({fill:'#3800BA'},1500); k++; }, function(){ setTimeout(Anim, 1600); }) } Anim();
需要注意的是,我们必须在step_animate开始前对相应属性初始化。 同时setTimeout应该在所有子元素的动画都完成之后再开始。
而如果我们要加入多重动画的话,则我们必须嵌套多层step_animation。
最后再进行了一些调整和内容的丰富, 预览见 Demo
本文完