SVG——新一代Web设计及互动媒体的革新

蓝骑士SVG教程:SVG动态与动画 - 第三课 结合JavaScript产生SVG动画

文章索引
蓝骑士SVG教程:SVG动态与动画
第一课 SVG的变形属性
第二课 SVG动画
第三课 结合JavaScript产生SVG动画
第四课 SVG鼠标事件
第五课 SVG键盘事件
第六课 动态插入SVG元素
所有页面
  有时仅仅使用一般的标准SVG动画元素并不能达到所需的动画效果.例如,也许你想产生一些无级变化(类似无级变速),或者是随机的改变一个属性值,或者根据 某一个非线性公式来确定运动中的某些变化数值,这时候,结合与SVG相关联的JavaScript和DOM,你依然可以得到你所需要的.

  下面是一个JavaScript动画的例子.



  上面的例子实时的在改变紫色部分元素的"d"属性.

  所有的动画所需要的JavaScript代码都在SVG文件中被写入.这时图像更容易的在任何网页中被使用.

  动画由SVG标签中的"被载入"(onload)引发."onload"句柄保存了动画的初始值,通过调用系统中的setInternal函数让浏览器开始播放动画.

function on_load (event)
{
// Save a pointer to the SVGDocument object
// so that we can use it to retrieve various
// named elements inside the animation function.
svgdoc = event.getCurrentNode().getOwnerDocument();

// Start the animation loop.
setInterval ('next_frame()', 100);
}
  注意:这其实只是一种单存的逼近效果,并不是指下一帧图像一定是在100微妙后被调用.实际的时间取决于每一台机器的性能.同时也请注意,这一内部的时间值数可以变动,使用较大的时间数会让动画变慢和粗糙,使用较小的时间数会让动画变快和光滑.

  上述的过程构成了绝大多数的JavaScript动画原理.在next_frame方程中,使用svgdoc的值,你可以定义任何在SVG文件中你所需要定义的元素.看看下面的解释让我们更进一步的了解next_frame函数.

  动态变化的线段是贝赛尔曲线在SVG文件宽度上的一段线段.贝赛尔曲线需要两个控制点.动画的形成就是经常性的改变这两个控制点而保持线段首尾的固定.我们 随机的产生一些"目标"target数值来控制点的一致性,也就是我们逐渐的减少或增加当前点的数值使之逐渐逼近"目标"target的数值.



  在next_frame方程中,我们使用4个通用的变量来保持当前的点的一致,它们分别是:(x0,y0)第一控制点.(x1,y1)第二控制点;我们也使用另4个通用的变量,来获得目标的坐标值:(tx0,ty0),(tx1,ty1).

  next_frame方程的第一步是使用DOM的方法重新获取(path)元素的句柄.svgdoc的句柄的获得则在SVG文件被调用的同时,由on-load时间触发.

var linenode = svgdoc.getElementById ('line');
if (!linenode)
return;
  接着,如果需要,我们产生一个新的目标值来控制点的x和y值. 这个产生新的目标值过程既可以在一开始时调用(此时目标值还为-1)也可以在当前值与目标值一致的时候调用新的目标值.

if (tx0 < 0
|| (tx0 == x0 && ty0 == y0 && tx1 == x1 && ty1 == y1))
{
tx0 = Math.floor (400*Math.random());
ty0 = Math.floor (300*Math.random());
tx1 = Math.floor (400*Math.random());
ty1 = Math.floor (300*Math.random());
}
  然后,我们以+/-10个像素点的大小改变目标点值,来获得新的目标点.这由一个分离的过程函数来执行(分离这一过程函数是为了使代码更简洁,请参看SVG的源文件)

x0 = change_coord (x0, tx0);
y0 = change_coord (y0, ty0);
x1 = change_coord (x1, tx1);
y1 = change_coord (y1, ty1);
  最后我们改变路径元素的"d"属性,用来产生新的相关性,实现运动的连续.记得这是一个路径的完整的设置,一个开始点,两个控制点,和一个结束点,然后用贝赛尔曲线插值.

linenode.setAttribute
('d', 'M0,300L0,150C'+x0+','+y0+','+x1+','+y1+',400,150L400,300z');


 

将要更新