微信小程序实现信封红包拆开动画

962 阅读2分钟

最近接到一个需求,需要在小程序页面上加一个活动优惠券入口浮窗。然后看了一下UI图,最开始就是这个样子,一个gif图,会自动放大缩小闪烁。

1659104942(1).jpg

正常开发来说,就拿这张gif放上去就可以了。但是看了下这个UI,感觉可以做的好一点,比如这样: 刚开始的时候红包是默认合起来的,然后自动打开红包,里面的内容像信封一样抽出来。

默认状态:

1659104870(1).jpg

过渡效果:

1659104979(1).jpg

这样做的好处不仅有了一个很直观顺滑的动画效果,而且里面的文本内容还可以自定义。

于是话不多说,开干:

一、拆解红包构成:

               1、顶部的信封头div
               2、中间的信封内容div
               3、下方压住信封主体内容的div
               4、信封红包主背景div

二、这样下来,就需要下面这几张背景图了。

coupon_head.png

coupon-bottom.png

coupon_body.png

三、有了这几张基础背景图,下面就是搭建基础的页面结构:

wxml部分

    <view class="traffic-withdraw">
        <view class="withdraw-container {{ withdrawOpen?'open':'' }} {{ withdrawDown?'down':'' }}">
            <view class="coupon-head"></view>
            <view class="coupon-content"></view>
            <view class="coupon-bottom"></view>
            <view class="coupon-body"></view>
        </view>
    </view>

wxss部分:核心动画功能就是利用css3的transform-origin以及transform: rotateX来实现顶部的红包打开效果。

.traffic-withdraw{
    position: fixed;
    top: 800rpx;
    left: 630rpx;
    z-index: 1002;
    .withdraw-container{
        float: right;
        width: 107rpx;
        height: 93rpx;
        .coupon-body{
            width: 100%;
            height: 100%;
            background: url('https://file.40017.cn/groundtraffic/urpt/coupon_body.png') top left no-repeat;
            background-size: 100% 100%;
        }
        .coupon-head{
            position: absolute;
            transform-origin: 0 0;
            z-index: 12;
            top: 0;
            left: 0;
            width: 107rpx;
            height: 39rpx;
            background: url('https://file.40017.cn/groundtraffic/urpt/coupon_head.png') top left no-repeat;
            background-size: 100% 100%;
            transition: all 1s ease 1s;
        }
        .coupon-content{
            position: absolute;
            transform-origin: 0 0;
            z-index: 10;
            top: 0;
            left: 5.5rpx;
            width: 98rpx;
            height: 80rpx;
            background: url('https://file.40017.cn/groundtraffic/urpt/coupon_content.png') top left no-repeat;
            background-size: 100% auto;
            transition: all 1s ease;
        }
        .coupon-bottom{
            position: absolute;
            z-index: 11;
            bottom: 0;
            left: 0;
            width: 107rpx;
            height: 70rpx;
            background: url('https://file.40017.cn/groundtraffic/urpt/coupon-bottom.png') bottom left no-repeat;
            background-size: 100% 100%;
        }
        &.open{
            .coupon-head{
                transform: rotateX(-270deg);
                transition: all 1s;
            }
            .coupon-content{
                top: -35rpx;
                transition: top 1s ease-in-out 1s;
            }
        }
      
    }
}

然后js部分就是设置一个定时器,来回切换withdrawOpen布尔值,从而达到想要的动画效果。 js部分

    // 设置定时器timer
    let trafficWithdrawTimer = null
    
    Page({
        data: {},
        onLoad(){},
        onShow(){
            this.setWithdrawTimer(true)
        },
        setWithdrawTimer(flag){
            let { withdrawOpen } = this.data
            if(trafficWithdrawTimer){
                this.clearTrafficWithdrawTimer()
            }
            trafficWithdrawTimer = setTimeout(()=>{
                this.setData({
                    withdrawOpen: !withdrawOpen
                })
                this.setWithdrawTimer()
            }, flag ? 1000 : 6000)
        },
        clearTrafficWithdrawTimer(){
            if(trafficWithdrawTimer){
                clearTimeout(trafficWithdrawTimer)
                trafficWithdrawTimer = null
            }
        },
    })