小程序动画循环方案

2019-08-21  本文已影响0人  姜姜蒋

小程序中适当使用微型动画,可以给交互带来更好的体验。


demo做的是一个刷新动画。 点击banner右下角的“刷新”图标,拉取接口,获取新图片地址,刷新banner图。 我希望的效果是在这个过程中,图标一直转圈,直到图片刷新成功。

按照小程序开发指南的介绍,在小程序中,通常可以使用 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 属性的值可以做到动画效果。实现复杂场景动画。

上一篇下一篇

猜你喜欢

热点阅读