小程序中适当使用微型动画,可以给交互带来更好的体验。
按照小程序开发指南的介绍,在小程序中,通常可以使用 CSS 渐变 和 CSS 动画 来创建简易的界面动画。同时,还可以使用 wx.createAnimation 接口来动态创建简易的动画效果。实际使用发现css动画更容易实现。以下是两种实现方案代码。
小程序动画API creatAnimation
首先创建一个动画实例(描述动画持续时间,延迟执行时间,动画运行曲线,原点),然后往这个实例里面添加动画组,每组动画可以包含很多动作(旋转、缩放、位置变换等等),这些动作是同时执行的,一组动画执行完毕后,继续执行下一组动画。动画组全部添加好了,通过动画实例的 export 方法导出动画数据 setData 给组件的 animation 属性。官方文档
wxml:
<!--给button组件添加animation属性, 图标使用的是iconfont -->
<button class="button" bindtap="refresh" animation="{{animationData}}" >
<icon class="iconfont iconhuanyipi" />
</button>
js:
onReady() {
// 创建动画
this.animation = wx.createAnimation({
duration: 1000 // 默认持续时间1000ms
});
},
refresh() {
this.animation.rotate(360).step(); // 往animation里面添加转圈动画组
// 导出动画,传递给组件
this.setData({
animationData: this.animation.export()
});
// 调接口,获取新图片地址,成功后动画停止
...
}
写到这里,发现小程序动画API少了一些东西:
1.有动画持续时间 duration属性,单位是ms,可是没有类似css3中的 infinite 无限循环。 要实现无限循环,需要自己写代码实现。
2.转圈动画只能转一次,再次点击不转圈了。原因动画执行后,图标是旋转360度的状态,没有回到原点。需要自己写代码回到原点。
this.animation.rotate(0).step({ duration: 0 }); // 动画持续时间设置为0
3.实现了动画循环,还要在适当的时候停止动画,小程序也没有停止动画的功能提供。需要自己写代码实现。
4.小程序动画的原理,是不停的改变wxml 元素的style属性,估计执行复杂动画有性能瓶颈,卡顿的可能。 我用到动画的比较简单,暂时没有发现这个问题。
幸好,在小程序开发指南里面还提供了 bindtransitionend 来监听动画结束一个阶段。 这个事件为循环动画,和停止动画提供了可能。 注意这里监听的是动画结束一个阶段,也就是上面提到的一个动画组(step)。每次结束都会调用。
wxml: 增加了一个 bindtransitionend 事件,监听每组动画结束
<view class="button" bindtap="refresh" animation="{{animationData}}" bindtransitionend="reAnimation">
<icon class="iconfont iconhuanyipi" />
</view>
js: 增加 circling 来记录动画状态(动画中,或者停止),增加 bindtransitionend方法
data:{
animationData: {},
},
onReady() {
// 创建动画
this.animation = wx.createAnimation({
duration: 1000
});
this.circling = false; // 记录动画状态
},
refresh() {
this.animation.rotate(360).step(); // 往animation里面添加转圈动画组
// 导出动画,传递给组件
this.setData({
animationData: this.animation.export()
});
this.circling = true;
// 模拟调用接口延时,3秒后停止动画
setTimeout(()=>{
this.circling = false;
},3000)
},
// 监听wx动画step结束
reAnimation(val) {
console.log("reAnimation",val)
if (!this.circling) {
console.log("结束动画");
this.animation.rotate(0).step({ duration: 0 });
this.setData({
animationData: this.animation.export()
});
} else {
console.log("循环动画");
// 先把旋转回归到初始0度,然后重新设置动画组,两次setData必须有时间差(这里写的60ms),否则不生效
this.animation.rotate(0).step({ duration: 0 });
this.setData({
animationData: this.animation.export()
});
this.animation.rotate(360).step();
setTimeout(() => {
this.setData({
animationData: this.animation.export()
});
}, 60);
}
},
经过一番折腾总算勉强实现了!动画的停止只能在完成一组动作后实现,中途不能停止。
css3动画实现
同样的效果,如果使用css3动画来实现,会简单很多。首先在wxss里面引入css3动画样式,我习惯用animate.css
@import "./animate.wxss";
<view class="button animated infinite {{animateName}}" bindtap="refresh">
<icon class="iconfont iconhuanyipi" />
</view>
data: {
animateName: "" //
},
refresh() {
this.setData({
animateName: "circle"
});
// 模拟调用接口延时,3秒后停止动画
setTimeout(()=>{
this.setData({
animateName: ""
});
},3000)
}
ps:
小程序另外还有“高级动画方式”:WXS 响应事件。通过wxs事件不断改变 style 属性的值可以做到动画效果。实现复杂场景动画。