Recently, the company needs to do a wechat red packet rain function. The basic online search is to use canvas, which is not very skilled in canvas, so I wrote one with css. This method works well for apple, but there will be a jam situation on Android. After several optimizations, there will be a little jam, not much nonsense, code:
wxml:
<view> //5 seconds before red packet starts <view wx:if="{{showBefore}}" class="beforeRain"> <view bindtap="clearTimer" class="bfText">A wave of red envelopes is coming</view> <view class="timeing">{{beforeTime}}</view> </view> //Red bag begins to fall <view wx:if="{{showBegin}}" class="beginRain"> <view wx:if="{{rainTime>0}}" class="beginText"> {{pocketNum}} </view> <view wx:if="{{rainTime>0}}" class="ge">individual</view> <view wx:if="{{rainTime>0}}" class="rainTime">00:{{rainTime>9?'':'0'}}{{rainTime}}</view> <view class="pocketList"> <block wx:for="{{imagesList}}" wx:key="index"> <image wx:if="{{index==idx?false:true}}" bindtap="getPocket" data-idx='{{index}}' class="pocket" style="position:fixed;transform:translateY({{magtop}}px) rotate({{item.tranRota}}deg);left:{{item.magLeft}}rpx;transition:{{item.downTime}}ms linear {{item.delatTime}}ms;" src="{{item.ulr}}" /> //Here is to set the red packet to disappear after clicking the red packet. At the same time, the red packet drop and rotation angle are controlled through the transition attribute </block> </view>> </view> //Show that the red bag has been robbed and removed after the red bag is robbed <view wx:if="{{showAfter}}" class="afterCss"> <view class="bgAllPoct" style="background-image: url({{'https://open.huaximeiyekeji.com/static/img/wx/redpack/bg-gos.png?'+suijiNum}});"> <view class="allPoct"> <view class="allbox"> <block wx:for="{{allPocket}}" wx:for-index="index"> <view bindtap="{{item.downId==1?'':'allOpenPoct'}}" data-Num="1" data-ind="{{index}}" class="{{item.downId==1?'openPock':'poct'}}" style="transform:rotateY({{item.downId}}turn);background-image:url({{item.imgUrl}});"> <block wx:if="{{item.imgUrl!='https://open.huaximeiyekeji.com/static/img/wx/redpack/w-open.png'}}"> <view class="money">¥{{item.money}}</view> <view class="mongName">{{item.type==0?'Sub card':item.type==1?'Discount card':item.type==2?'Rechargeable card':item.type==10?'Full and reduced coupon':item.type==11?'Cash coupon':item.type==12?'Air ticket':''}}</view> </block> </view> </block> </view> <view class="text">The right to explain the event belongs to our store</view> </view> <image class="allOpen" bindtap="allOpenPoct" data-Num="{{pocketNum}}" src="{{'https://open.huaximeiyekeji.com/static/img/wx/redpack/one-btn.png?'+suijiNum}}"></image> <image bindtap="closeImg" class="closeAll" src="./images/close.png"></image> </view> </view> <block wx:if="{{showCont}}"> <view class="PoctCont"> <image bindtap="closeImgSm" class="closeSm" src="./images/closed.png"></image> <view class="contTextBox"> <view class="contText" wx:for="{{pocketList}}" wx:key="index"> <view class="contName">{{item.name}}</view> <view class="contMoney"><span style="font-weight: bold;">{{item.mvalue}}</span>element</view> </view> </view> </view> </block> </view>
js:
const app = getApp() Component({ properties:{ bcstId:Number, shopId:Number }, options:{ multipleSlots: true }, data: { items: [], currentItem: 0, beforeTime:5, loanTime:'', topList:100, showBefore:true, showBegin:false, showAfter:false, rainTime:20, allPocket:[], minRotate:'', pocketImg:'https://open.huaximeiyekeji.com/static/img/wx/redpack/w-open.png', pocketNum:0, DropPocket0:'', maxRotate:'', beginLoan:'', magtop:0, numes:'', imagesList:[ {ulr:'./images/redPacket.png',jiaodu:Math.floor(Math.random()*180)-100,downTime:Math.floor(Math.random()*7000)+5000,delatTime:Math.floor(Math.random()*10000),magLeft:(Math.random()*620)+30,tranRota:Math.floor(Math.random()*360),showPoc:true}, {ulr:'./images/redPacket.png',jiaodu:Math.floor(Math.random()*180)-100,downTime:Math.floor(Math.random()*7000)+5000,delatTime:Math.floor(Math.random()*10000),magLeft:(Math.random()*620)+30,tranRota:Math.floor(Math.random()*360),showPoc:true}, {ulr:'./images/redPacket.png',jiaodu:Math.floor(Math.random()*180)-100,downTime:Math.floor(Math.random()*7000)+5000,delatTime:Math.floor(Math.random()*10000),magLeft:(Math.random()*620)+30,tranRota:Math.floor(Math.random()*360),showPoc:true}, {ulr:'./images/redPacket.png',jiaodu:Math.floor(Math.random()*180)-100,downTime:Math.floor(Math.random()*7000)+5000,delatTime:Math.floor(Math.random()*10000),magLeft:(Math.random()*620)+30,tranRota:Math.floor(Math.random()*360),showPoc:true}, ], idx:'', rotateX3D:0, ind:'', suijiNum:'', getPoctCont:'', pocketList:[], openNum:1, showCont:false }, //Event triggering, prepare for falling. Note that several parameters, angles, falling time and delayed falling in the images array are all random. Falling time and delayed falling time are all in ms. otherwise, there will be wave by wave situations, and the feeling is inconsistent ready: function () { this.setData({ suijiNum:Math.floor(Math.random()*7000)+5000 }) this.timer() }, methods: { closeImg(){ this.setData({ showAfter:false }) }, //Dismantle a red envelope allOpenPoct(e){ //Request interface this.setData({ ind:e.currentTarget.dataset.ind, }) //One or all if(e.currentTarget.dataset.num==1){ this.setData({ numes:1, }) }else{ this.setData({ numes:this.data.pocketNum, }) } app.get({ url: 'bo/cc/open', login: true, data: { wxId:app.state.wxuser.id, id: this.data.bcstId, shopId:this.data.shopId, num:this.data.numes }, success: e => { if (e.code !== 0) return; if(this.data.numes>1){ for(var i=0;i<e.data.length;i++){ e.data[i].cc.mvalue = e.data[i].cc.mvalue/100 this.data.pocketList.push(e.data[i].cc) } this.setData({ showCont:true, showAfter:false, pocketList:this.data.pocketList }) console.log(this.data.pocketList) }else{ this.data.openNum = this.data.openNum+1 this.data.getPoctCont = e.data[0].cc this.data.getPoctCont.mvalue = this.data.getPoctCont.mvalue/100 this.data.pocketList.push(this.data.getPoctCont) this.setData({ pocketList:this.data.pocketList }) console.log(this.data.pocketList) for(var i=0;i<this.data.allPocket.length;i++){ if(this.data.ind==i){ this.data.allPocket[i].type = this.data.getPoctCont.type this.data.allPocket[i].money = this.data.getPoctCont.mvalue } } } }, }) //Processing data for(var i=0;i<this.data.allPocket.length;i++){ if(i==this.data.ind){ this.data.allPocket[i].downId = 1 } } this.setData({ allPocket:this.data.allPocket }) setTimeout(()=>{ for(var n=0;n<this.data.allPocket.length;n++){ if(n==this.data.ind){ this.data.allPocket[n].imgUrl = 'https://open.huaximeiyekeji.com/static/img/wx/redpack/get.png?'+this.data.suijiNum } } this.setData({ allPocket:this.data.allPocket }) },2000) if(this.data.openNum==this.data.allPocket.length){ setTimeout(()=>{ this.setData({ showCont:true, showAfter:false }) },3000) } }, closeImgSm(){ this.setData({ showCont:false }) }, //Click to grab red envelopes getPocket(e){ if(this.data.pocketNum<3){ var jsn ={} jsn.downId = 0 jsn.imgUrl = this.data.pocketImg this.data.allPocket.push(jsn) this.setData({ idx:e.currentTarget.dataset.idx, pocketNum:this.data.pocketNum+1, }) }else{ wx.showToast({ title:"You've robbed three red envelopes", icon:"none" }) } }, timer() { let that = this that.data.loanTime = setInterval(function() { if(that.data.beforeTime>0){ that.setData({ beforeTime: that.data.beforeTime-1 }) }else{ that.clearBeforTimer() that.setData({ showBefore:false, showBegin:true }) that.beginRain() } }, 1000) }, beginRain(){ let that = this // for(var i=0;i<that.data.imagesList.length;i++){ // var jsObj = that.data.imagesList[i] // that.data.imagesList[i].magtop = 1000 // } that.setData({ magtop:1200 }) console.log(that.data.magtop,"======") // that.setData({ // imagesList:that.data.imagesList // }) that.data.beginLoan = setInterval(()=>{ if(that.data.rainTime>0){ that.setData({ rainTime:that.data.rainTime-1 }) }else{ that.clearBeginTimer() that.setData({ showBegin:false, showAfter:true, allPocket:that.data.allPocket }) } },1000) }, afterRain(){ }, clearBeforTimer(){ clearInterval(this.data.loanTime) }, clearBeginTimer(){ clearInterval(this.data.beginLoan) } } })
css:
/* pages/index/index.wxss */ .beforeRain{ height: 100vh; width: 100vw; position: fixed; top: 0; left: 0; background-color: rgba(0, 0, 0, 0.5); color: #FCFED9; } .bfText{ margin-top: 30vh; font-size: 60rpx; text-align: center; } .timeing{ font-size: 200rpx; text-align: center; } .beginRain{ position: fixed; top: 0; left: 0; height: 100vh; width: 100vw; background-image: url(https://open.huaximeiyekeji.com/static/img/wx/redpack/bg.png); / * this must be a network picture. The local picture cannot be displayed*/ background-size: 100% 100%; background-repeat: no-repeat } .beginText{ width: 88rpx; height: 115rpx; text-align: center; background-image: url(https://open.huaximeiyekeji.com/static/img/wx/redpack/redpack.png); / * this must be a network picture. The local picture cannot be displayed*/ background-size: 100% 100%; background-repeat: no-repeat; font-size: 30rpx; color: #FCFED9; position: fixed; right: 20rpx; line-height: 70rpx; top: 170rpx; } .ge{ font-size: 18rpx; font-weight: 200; color: #FCFED9; right: 28rpx; top: 195rpx; position: fixed; z-index: 1; } .rainTime{ position: fixed; right: 20rpx; top: 290rpx; color: #ffebcd; width: 88rpx; text-align: center; font-size: 30rpx; } .pocket{ height: 100rpx; width: 80rpx; transition-property:all;/*Here is to define the type of animation, select all It's OK, but it must be used transform Property, so the page performance is high, such as( height,left,margin)This property performance is very low. There are detailed tutorials at night transform-origin:50% 50% 0; } .pocketList{ position: fixed; top: -250rpx; } .allPoct{ height: 400rpx; width: 555rpx; position: fixed; top: 500rpx; left:105rpx; } .poct{ height: 206rpx; margin-top: 40rpx; width: 162rpx; margin-left: 19rpx; float: left; background-repeat: no-repeat; background-size: 100%; vertical-align: bottom; transition: transform 2s linear; } .openPock{ height: 262rpx; width: 162rpx; margin-left: 19rpx; float: left; vertical-align: bottom; background-repeat: no-repeat; background-size: 100%; transition: transform 2s linear; } .bgAllPoct{ width: 708rpx; height: 868rpx; position: fixed; left: 21rpx; top: 150rpx; background-size: 100% 100%; background-repeat: no-repeat; z-index: 2; } .afterCss{ width: 100vw; height: 100vh; position: fixed; background-color: rgba(0,0,0,0.4); top: 0; left: 0; z-index: 1; } .allOpen{ width: 440rpx; height: 100rpx; position: fixed; top: 875rpx; left:155rpx ; } .closeAll{ height: 56rpx; width: 56rpx; position: fixed; top: 1050rpx; left: 347rpx; } .text{ font-size: 21rpx; color: #977144; text-align: center; } .allbox{ height: 280rpx; width: 100%; } .money{ margin-top: 48rpx; text-align: center; font-size: 24rpx; color: #977144; } .mongName{ text-align: center; font-size: 20rpx; color: #977144; } .PoctCont{ background-image: url('https://open.huaximeiyekeji.com/static/img/wx/redpack/bg-list.png'); background-repeat: no-repeat; background-size: 100%; height: 650rpx; width: 420rpx; position: fixed; top: 350rpx; left: 165rpx; } .closeSm{ height: 28rpx; width: 28rpx; margin-left: 20rpx; margin-top: 20rpx; } .getPoctCont{ display: flex; } .contTextBox{ margin-top: 150rpx; } .contText{ padding:20rpx; display: flex; font-size: 24rpx; color: #D4870E; } .contName{ flex: 1; text-align: left; } .contMoney{ width: 130rpx; text-align: right; }
The above is basically the case. Pure css realizes the red packet rain of wechat applet. The bug is that the Android machine will display a jam. Do you have any good suggestions? Welcome to guide