这次介绍一款强大的SVG动画转换
http://alexk111.github.io/SVG-Morpheus/alexk111.github.io
查了下morph的意思,是一个动词
(使)变形(利用电脑动画制作使图像平稳变换) ; (使) 变化; (使) 改变
先看一下效果
一开始我以为只能切换默认的一些Icon,后来发现它果真是强大,理论上是能动画切换任何SVG的,也支持设置如下的参数
我做了一下简单的尝试,从左边的同心圆,动画转换到右边的圆角矩形。
下面看放慢到10秒的效果
本着好奇的精神,我还是略作查看,每当这种动画库想要深入的时候,发现背后全是数学知识。
万事都是冰箱三部曲。
const svgMorpheus = new SVGMorpheus("#icon");
这里主要是看在SVGMorpheus
的构造函数里,它做了点什么小动作。
吃进去的是草
挤出的是奶
我们看到在SVGMorpheus
内部它已经偷偷地转成了
标签,并且和原来的绘图效果完全一致,抠出源码一看
case 'CIRCLE':var cx=nodeItem.getAttribute('cx')*1,cy=nodeItem.getAttribute('cy')*1,r=nodeItem.getAttribute('r')*1;item.path='M'+(cx-r)+','+cy+'a'+r+','+r+' 0 1,0 '+(r*2)+',0a'+r+','+r+' 0 1,0 -'+(r*2)+',0z';
break;
其他诸如
、
等都是有对应的转换方式。
如此第一步把冰箱打开已经完成,可以猜测,之后肯定是在
上做文章。
接下来要实现动画就要如此调用
svgMorpheus.to("rect", {duration: 10000
});
再看源码可以知道建立起动画计算主要是调用了
this._setupAnimation(iconId);
首先要有from
和to
两个形状
this._fromIconItems=clone(this._curIconItems);
this._toIconItems=clone(this._icons[toIconId].items);
由于这两个图形一个是有两个
,一个只有一个
,所以第一步要先把两者填平,在节点数上一致,填进来的效果也很简单,要么是从无到有,要么是从有到无。
接下来的事情就是每个
一对一单挑了,核心就是这个方法
var curves=path2curve(this._fromIconItems[i].path,this._toIconItems[i].path);
先看curves
的结果,它把M12,10l36,0a2,2 0 0,1 2,2l0,36a2,2 0 0,1 -2,2l-36,0a2,2 0 0,1 -2,-2l0,-36a2,2 0 0,1 2,-2z
这样的字符串,转化成
这样的数组。另外不光有path
,还有style
和rotate
的计算。
拿到了起点和终点的对比数据之后,相当于把大象放进了冰箱,就可以开始做显示了,内部也是用的raf
。
var _reqAnimFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.oRequestAnimationFrame;
var _cancelAnimFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.oCancelAnimationFrame;
主要看SVGMorpheus.prototype._updateAnimationProgress
这个方法,核心就是按照当前进度计算属性变化的值
关上冰箱门的步骤也完成了。
最后我觉得这款动画库是能实现任何图形的动画转换,但是由于需要大量的计算和不停的渲染,致使它在性能上肯定有短板,而作者应该也是意识到这一点,给它的定位是只局限在图标上的动画库。
Javascript library enabling SVG icons to morph from one to the other.
比较可惜的是作者说这个库不再维护了。