当前位置:   article > 正文

微信小程序实现拆红包动画_小程序 打开红包的动画

小程序 打开红包的动画

1.实现效果

在这里插入图片描述

2.实现原理

wx.createAnimation(Object object):创建一个动画实例 animation。调用实例的方法来描述动画。最后通过动画实例的 export 方法导出动画数据传递给组件的 animation 属性。

  • 点击红包,弹出红包弹框,用到过渡动画
this.animation.translate('-50%', '-50%').step();
  • 1
  • 关闭弹框
this.animation.translate('-50%', '100%').step();
  • 1
  • 将红包弹框拆分成两部分,后续点击开红包时候的上下两部分反向淡出动画

在这里插入图片描述

   animation1.translateY('-350%').step();
   animation2.translateY('300%').step()
  • 1
  • 2
  • 当开红包动画结束,关闭弹框,并清除动画,这里用opacity来清除动画(一般情况按照原来的样式复原即可,因为该处原本无transfrom属性,还原动画若添加transfrom会影响页面布局,即用opacity)
 animation1.opacity(1).step();
 animation2.opacity(1).step();
  • 1
  • 2
  • 上下两部分的圆弧用伪元素+border-radius+box-shadow实现
  • 点击开红包,添加动画

@keyframes rotate {
  0% {
    transform: rotateY(0deg);
  }

  100% {
    transform: rotateY(360deg);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.实现代码

<view class="flex">
  <image src="https://i.postimg.cc/mgsKJGLw/susu1.jpg" class="user_avatar" />
  <view class="wallet_box" catchtap="show">
    <view class="flex-row j_c">
      <image src="../img/red.png" class="red_icon" />
      <view>恭喜发财,大吉大利</view>
    </view>
    <view class="wallet_tip">微信红包</view>
  </view>
</view>
<!-- 红包弹框 -->
<view class="mask" hidden="{{!show}}"></view>
<view class="red_box flex-column" animation="{{animationData}}" hidden="{{!show}}">
  <view class="top flex-column" animation="{{animationData1}}">
    <view class="flex-row">
      <image src="https://i.postimg.cc/mgsKJGLw/susu1.jpg" class="user_avatar_dia" />
      <view>小苏苏的红包</view>
    </view>
    <view class="text">恭喜发财,大吉大利</view>
    <view class="top_radius">
      <view class="open" catchtap="open" wx:if="{{not_open}}"></view>
      <view wx:else class="anim-rotate">
        <view class="roate_box" style="transform: translateZ(-3px);"></view>
        <view class="roate_box roate_box_center" wx:for="{{5}}" wx:key="index" style="transform:translateZ({{index-3}}px)"></view>
        <view class="roate_box roate_box_center" style="transform: translateZ(3px);"></view>
      </view>
    </view>
  </view>
  <view class="bottom" animation="{{animationData2}}">
    <view class="line"></view>
    <view class="bottom_box"></view>
  </view>
  <image src="/img/close_icon.png" class="close_icon" catchtap="closeModal" />
</view>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
/* pages/effects/clipRed/index.wxss */
page {
  padding: 20rpx;
  box-sizing: border-box;
  background-color: #fff;
}

.user_avatar {
  width: 60rpx;
  height: 60rpx;
  border-radius: 10rpx;
  flex-shrink: 0;
  margin-right: 30rpx;
}

.wallet_box {
  position: relative;
  width: 360rpx;
  height: 140rpx;
  border-radius: 10rpx;
  background-color: orange;
  box-sizing: border-box;
  padding: 10rpx 21rpx;
  color: #fff;
  font-size: 25rpx;
}

.red_icon {
  width: 70rpx;
  height: 70rpx;
  flex-shrink: 0;
  margin-right: 10rpx;
}

.wallet_box::after {
  content: '';
  position: absolute;
  top: 20rpx;
  left: -15rpx;
  width: 0;
  height: 0;
  border-top: 20rpx solid transparent;
  border-bottom: 20rpx solid transparent;
  border-right: 20rpx solid orange;
}

.wallet_tip {
  border-top: 1rpx solid rgb(255, 255, 255, .2);
  margin-top: 10rpx;
  padding-top: 10rpx;
  font-size: 20rpx;
}

.red_box {
  position: fixed;
  left: 50%;
  transform: translate(-50%, 100%);
  top: 50%;
  color: rgb(235, 205, 153);
  width: 530rpx;
  z-index: 1222;
  font-size: 27rpx;
}

.top {
  position: relative;
  border-radius: 15rpx 15rpx 0 0;
  width: 100%;
  padding: 175rpx 0 0rpx;
  box-sizing: border-box;
  background-color: #f45e4d;
}

.top_radius {
  width: 100%;
  height: 100px;
  position: relative;
}

.top_radius::after {
  width: 100%;
  height: 100px;
  position: absolute;
  left: 0;
  top: 52px;
  content: '';
  border-radius: 50%;
  z-index: 10;
  background-color: rgb(244, 94, 77);
  box-shadow: 0 3px 3px 0 rgb(0 0 0 / 10%);
}

.close_icon {
  position: absolute;
  width: 50rpx;
  height: 50rpx;
  bottom: -91rpx;
}

.user_avatar_dia {
  margin-right: 10rpx;
  width: 40rpx;
  height: 40rpx;
  border-radius: 8rpx;
  flex-shrink: 0;
}

.text {
  font-size: 36rpx;
  margin-top: 20rpx;
}

.bottom {
  overflow: hidden;
  width: 100%;
  margin-top: -70rpx;
}

.bottom_box {
  margin-top: 70rpx;
  height: 240rpx;
  background-color: rgb(242 85 66);
  border-radius: 0 0 15rpx 15rpx;
}

.line {
  width: 100%;
  position: relative;
}

.line::after {
  width: 120%;
  height: 140rpx;
  position: absolute;
  left: -10%;
  top: -70rpx;
  z-index: -1;
  content: '';
  border-radius: 50%;
  box-shadow: 0 30px 0 0 rgb(242 85 66);
}

.open {
  -webkit-transform: translateX(-50%);
  transform: translateX(-50%);
  position: absolute;
  left: 50%;
  z-index: 99;
  bottom: -161rpx;
  border-radius: 50%;
  width: 130rpx;
  height: 130rpx;
  line-height: 130rpx;
  font-size: 45rpx;
  text-align: center;
  color: #333;
  font-weight: bold;
  background-color: rgb(235, 205, 153);
  box-shadow: 0 0 3rpx 0 rgb(0 0 0 / 10%);
}

.roate_box {
  border-radius: 50%;
  width: 130rpx;
  height: 130rpx;
  line-height: 130rpx;
  font-size: 45rpx;
  text-align: center;
  color: #333;
  font-weight: bold;
  background-color: rgb(235, 205, 153);
  box-shadow: 0 0 3rpx 0 rgb(0 0 0 / 10%);
}

.anim-rotate {
  margin-left: -75rpx;
  transform-style: preserve-3d;
  animation: rotate 1s linear infinite;
  position: absolute;
  left: 50%;
  z-index:90;
  bottom: -161rpx;
}

@keyframes rotate {
  0% {
    transform: rotateY(0deg);
  }

  100% {
    transform: rotateY(360deg);
  }
}

.roate_box_center {
  position: absolute;
  top: 0;
  z-index: 99;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
Page({
  data: {
    show: false,
    not_open: true,
    animationData: {},
    animationData1: {},
    animationData2: {},
  },
  closeModal() {
    this.slideIn(1);
    setTimeout(() => {
      this.setData({
        show: false
      })
    }, 200);
  },
  show() {
    wx.showLoading({
      title: '加载中...',
      mask: true
    })
    setTimeout(() => {
      this.setData({
        show: true
      }, (() => {
        this.slideIn(0)
      }))
      wx.hideLoading();
    }, 500);
  },
  open() {
    this.setData({
      not_open: false
    }, (() => {
      setTimeout(() => {
        this.setData({
          not_open: true,
        })
        this.fadeOut(() => {
          let animation = wx.createAnimation({
            duration: 0,
            timingFunction: 'step-end'
          })
          let animation1 = wx.createAnimation({
            duration: 0,
            timingFunction: 'step-end'
          })
          animation.opacity(1).step();
          animation1.opacity(1).step();
          this.setData({
            show: false,
            animationData1: animation.export(),
            animationData2: animation1.export(),
          })
        })
      }, 1000);
    }))
  },

  ....
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

4.完整代码,关注公众号 苏苏的bug,更多小程序demo,尽在苏苏的码云如果对你有帮助,欢迎你的star+订阅!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/284031
推荐阅读
相关标签
  

闽ICP备14008679号