最近接到一个需求,需要在小程序页面上加一个活动优惠券入口浮窗。然后看了一下UI图,最开始就是这个样子,一个gif图,会自动放大缩小闪烁。
正常开发来说,就拿这张gif放上去就可以了。但是看了下这个UI,感觉可以做的好一点,比如这样: 刚开始的时候红包是默认合起来的,然后自动打开红包,里面的内容像信封一样抽出来。
默认状态:
过渡效果:
这样做的好处不仅有了一个很直观顺滑的动画效果,而且里面的文本内容还可以自定义。
于是话不多说,开干:
一、拆解红包构成:
1、顶部的信封头div
2、中间的信封内容div
3、下方压住信封主体内容的div
4、信封红包主背景div
二、这样下来,就需要下面这几张背景图了。
三、有了这几张基础背景图,下面就是搭建基础的页面结构:
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
}
},
})