微信小程序:<cover-image>中使用rotate旋转动画的坑

@一棵菜菜  August 20, 2018

法1 --小程序动画

小程序的rotate动画在非<cover-*>标签上使用时没有什么问题的,但是在<cover-*>标签上使用时,我发现ios下只支持-180~180度的旋转(官方文档上也有范围备注),若超过则不旋转(如0~360度)。所以我让设计师出了一个图标旋转了-180度的图使用。

<map>
<!-- 刷新按钮 -->
    <cover-image src="./icon/refresh-btn.png" animation="{{animationData}}" bindtap="refreshAction" class="refresh-btn"></cover-image>
</map>
.refresh-btn {
    position: fixed;
    bottom: 195rpx;
    left: 8rpx;
    width: 102rpx;
    max-width: 102rpx;
    min-width: 102rpx;
    height: 102rpx;
    max-height: 102rpx;
    min-height: 102rpx;
    visibility: visible !important;

    /* 设置初始位置,因<cover-image>只支持-180~180度的旋转 */
    transform: rotate(-180deg);
    /*stylelint-disable*/
    -ms-transform: rotate(-180deg);
    -moz-transform: rotate(-180deg);
    -webkit-transform: rotate(-180deg);
    -o-transform: rotate(-180deg);
}
onLoad: function (options) {
        this.isIosEquipment();
        // 刷新按钮的动画init
        this.refreshBtnAnimation = wx.createAnimation({
            transformOrigin: '50% 50% 0',
            duration: 150,
            timingFunction: 'linear',
            delay: 0
        });
    },
/**
     * 是否是ios设备
     */
    isIosEquipment:function() {
        var that = this;
        wx.getSystemInfo({
            success: function (res) {
                // ios系统
                if (res.system.toLowerCase().indexOf('ios') > -1
                || res.platform.toLowerCase().indexOf('ios') > -1) {
                    that.setData({
                        isIos:true
                    });
                }
            }
        });
    },

复位原因:查看参考文章

this.refreshBtnAnimation.rotate(180).step({duration: 600});
这行代码表示,让它在600ms(初始化创建的时间)内旋转到180度,而是此时已处理180度啦,你再点击当然它不会再旋转了。它会不停报怨”我已在180度了呀,你还想怎么样?!...“

所以,此时,我们能不能直接再让旋转360度,那么它不就相对于180度后的状态又转了180度了吗?可是看看官网,旋转的范围是-180~180度,既使没有这么范围限制,那么我们也会折腾死,不是吗?每次都要1802,1803...

解决办法:就是直接让它复位归0度!这个归0度的动画时间必须要短,不然就要让人看到了一个”倒旋转的过程“,那么0s复位到0度,用户就查觉不到了。

具体代码如下:

/**
     * 刷新按钮的旋转动画
     * 注:<cover-image>只支持-180~180度的旋转
     */
    rotateAnimate: function () {
        if (!this.data.isIos) {
            this.refreshBtnAnimation.rotate(180).step({duration: 600});
            this.setData({
                animationData: this.refreshBtnAnimation.export()
            });

            // 复位至-180度(修复二次点击时不旋转bug,因已到达180度)
            clearTimeout(this.recoverRotateTimer);
            this.recoverRotateTimer = setTimeout(function() {
                this.refreshBtnAnimation.rotate(-180).step({duration: 0});
                this.setData({
                    animationData: this.refreshBtnAnimation.export()
                });
            }.bind(this), 600);
        } else {
            // 因ios下不可直接旋转-180至180度,否则会无旋转效果或旋转时位置乱跑偏等。so分为n个阶段
            this.refreshBtnAnimation.rotate(-90).step({duration: 150, transformOrigin: '50% 50% 0'});
            this.setData({
                animationData: this.refreshBtnAnimation.export()
            });
            var angle = -90;
            var timer = setInterval(function() {
                if (angle >= 180) {
                    clearInterval(timer);
                    return;
                }
                angle += 90;
                this.refreshBtnAnimation.rotate(angle).step({duration: 150, transformOrigin: '50% 50% 0'});
                this.setData({
                    animationData: this.refreshBtnAnimation.export()
                });
            }.bind(this), 150);

            // 复位(分多阶段复位)
            clearTimeout(this.recoverRotateTimer);
            this.recoverRotateTimer = setTimeout(function() {
                var angle = 180;
                var timer = setInterval(function() {
                    if (angle <= -180) {
                        clearInterval(timer);
                        return;
                    }
                    angle -= 90;
                    this.refreshBtnAnimation.rotate(angle).step({duration: 0, transformOrigin: '50% 50% 0'});
                    this.setData({
                        animationData: this.refreshBtnAnimation.export()
                    });
                }.bind(this), 0);
            }.bind(this), 600);
        }
    },
    /**
     * 刷新订单
     */
    refreshAction:function() {
        this.rotateAnimate();
        clearTimeout(this.refreshTimer);
        this.refreshTimer = setTimeout(function() {
            // 请求API接口
            this.getCarrierTrakingInfo();
        }.bind(this), 600);
    }

法2 --css法(适合H5,不适合小程序)

<map>
<!-- 刷新按钮 -->
    <cover-image src="./icon/refresh-btn.png" animation="{{animationData}}" bindtap="refreshAction" class="refresh-btn {{isActive?'rotate-animate':''}}"></cover-image>
</map>
.refresh-btn {
    position: fixed;
    bottom: 195rpx;
    left: 8rpx;
    width: 102rpx;
    height: 102rpx;

    /* 因<cover-image>只支持-180~180度的旋转 */
    transform: rotate(-180deg);
}

.rotate-animate {
    animation: rotateAnimate 600ms ease;
    -moz-animation: rotateAnimate 600ms ease;
    -webkit-animation: rotateAnimate 600ms ease;
    -o-animation: rotateAnimate 600ms ease;
}

@keyframes rotateAnimate {
  0% {
    transform: rotate(0deg);
    -ms-transform: rotate(0deg);
    -moz-transform: rotate(0deg);
    -webkit-transform: rotate(0deg);
    -o-transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
    -ms-transform: rotate(360deg);
    -moz-transform: rotate(360deg);
    -webkit-transform: rotate(360deg);
    -o-transform: rotate(360deg);
  }
}
/**
     * 刷新订单
     */
    refreshAction:function() {
        this.setData({
            isActive:true
        });
        clearTimeout(this.refreshTimer);
        this.refreshTimer = setTimeout(function() {
            this.getCarrierTrakingInfo();
            this.setData({
                isActive:false
            });
        }.bind(this), 650);
    }

添加新评论