使用 Snap.svg 来实现一个具有 morphing 动画效果的按钮动效
前面有专门写过一篇morphing动画基础知识的文章,不了解的话可以去这里看看。
今天这篇文章来讲一个morphing动画在UI界面上一个具体的运用即具有morphing动画效果的播放按钮。开始之前可以去YouTube网站上看看,它的播放和暂停按钮不是简单的切换,而是有一个过渡的动画效果,即morphing动画效果。如下图所示:
通过上面可以看出,播放与暂停之间的按钮是用一个morphing过渡的动画效果。当然像这么简单的效果使用CSS也可以实现。
但是如果有大量的类似的morphing按钮动画效果,使用SVG无疑会更加简单方便,实现效率也更高。下面就一步一步来完成这个morphing动画效果,这里会使用到snap svg 这个js库来作为基础的SVG操作库,它的作用就相当于jquery,提供了一整套的SVG解决方案,功能非常强大,详细的使用方法可以官方的文档地址看看。
具体实现的效果如下图所示:
准备工作
首先是在矢量设计软件中设计好播放与暂停两个按钮,然后导出path(路径),如下所示:
暂停按钮的path:
<svg width="288" height="288" viewbox="0 0 72 72"> <path d="M11,10 L18,13.74 18,22.28 11,26 M18,13.74 L26,18 26,18 18,22.28" /> </svg>
播放按钮的path:
<svg width="288" height="288" viewbox="0 0 72 72"> <path d="M11,10 L17,10 17,26 11,26 M20,10 L26,10 26,26 20,26" /> </svg>
因为我们这里会是在播放与暂停两个状态之间不停的切换,所以我们这里会使用SVG中的use来引用按钮。即先把两个按钮定义在defs标签中,然后通过use来引用具体的按钮。如下代码所示:
<div class="container"> <button class="button js-button"> <svg width="100%" height="100%" viewBox="0 0 36 36" id="svgicon" > <defs> <path id="pause-icon" data-state="playing" d="M11,10 L17,10 17,26 11,26 M20,10 L26,10 26,26 20,26" /> <path id="play-icon" data-state="paused" d="M11,10 L18,13.74 18,22.28 11,26 M18,13.74 L26,18 26,18 18,22.28" /> </defs> <use xlink:href="#play-icon" /> </svg> </button> </div>
在defs元素中,我们不但定义了播放和暂停两个按钮,还分别定义了自定义属性data-state即表示当前按钮的下一个状态,比如暂停按钮的下一个状态是播放(playing)。在后面实现morphing动画效果的时候要用到。
添加一些基本的样式:
.container { width: 500px; margin: 0 auto; } .button { padding: 0; width: 500px; height: 500px; border: 0; background-color: white; outline: none; }
运行效果如下图所示:
javascript编码实现morphing动画效果
首先在页面中引入Snap.svg文件:
https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js
js准备
先定义一个基本的方法:
var playButton = {};
获取基本的元素以及一些初始状态方法:
var playButton = { el: document.querySelector(".js-button"), //获取两个按钮 iconEls: { playing: document.querySelector("#pause-icon"), paused: document.querySelector("#play-icon") }, //用来存储按钮的两个状态 nextState: { playing: "paused", paused: "playing" }, //初始方法 init: function () { this.setInitialState(); this.replaceUseEl(); this.el.addEventListener("click", this.toggle.bind(this)); } }
这里来解释下初始方法:
setInitialState() 方法是用来获取当前按钮下一个的状态(data-state)属性的值的。
replaceUseEl() 方法是用来重置按钮的。因为要实现SVG Morphing动画效果,需要在path之间变换,所以需要在初始化的时候来使用path来代替use标签。而初始使用use标签是为了照顾页面在刚开始渲染的时候js还没加载完的时候能正常显示。
这两个方法都使用到了Snap.svg中的一些基本方法,比如新建一个SVG元素(path),就可以使用paper方法:
Snap("svgicon").paper.path();
上面的代码表示在ID为svgicon这个SVG标签中创建一个path元素。
一些初始化设置好后,接下来就是编写点击效果即点击的时候在播放和暂停之间切换并且带有Morphing动画效果。这里要使用到Snap.svg中animate方法:
Element.animate(attrs, duration, [easing], [callback])
参数
attrs 对象,描述属性的键值对。
duration 数值,动画持续的时间,单位是毫秒。
easing 函数,自定义的或者mina提供的缓动函数。
callback 函数,动画结束时候的回调。
下面来看下实现Morphing动画效果核心代码:
toggle: function () { var path = Snap.select('.js-icon'); this.goToNextState(); path.animate({ d:this.stateIconPath() },500,mina.linear); }, goToNextState: function () { this.state = this.nextState[this.state]; }, stateIconPath: function () { return this.iconEls[this.state].getAttribute("d"); }
所谓Morphing动画效果,就是从一个形状变到另一个形状。具体到我们这里就是在播放与暂停两个状态之间切换,由于按钮是path元素,所以只需要改变path元素中切换播放与暂停按钮中path元素中的d的值就可以了。
在toggle方法中,首先通过goToNextState()方法来获取当前按钮的下一个状态;通过stateIconPath()方法来获取当前按钮下一个状态的path属性中d的值,然后在animate方法中改变当前的path中的d的值即下一个按钮状态path中的d的值。由于使用animate方法,它们之间的变化会有一个动画效果即Morphing动画效果。
详细的代码可以去这里查看。
最近做了一个关于SVG的应用的技术分享网站svgtrick.com,会同步一些文章到这里来,更多的关于SVG方面的技术知识可以去网站看看。