如题,该小程序为一款利用canvas实现的转盘抽奖效果,今天我就来总结一下转盘旋转具体实现原理,首先还是上图上代码(一下代码为转盘部分代码,想要查看完整代码,请移步支我的github,飞机票,点击跳转)
wxml代码(中间转盘部分代码)
<view class="canvas-container" style='margin:0 auto;'> <view animation="{{animationData}}" class="canvas-content" style='margin:0 auto;'> <canvas style="width: 300px; height: 300px; margin:0 auto;" class="canvas-element" canvas-id="lotteryCanvas"></canvas> <view class="canvas-line"> <view class="canvas-litem" wx:for="{{awardsList}}" wx:key="unique" style="-webkit-transform: rotate({{item.lineTurn}});transform: rotate({{item.lineTurn}})"></view> </view> <view class="canvas-list"> <view class="canvas-item" wx:for="{{awardsList}}" wx:key="unique"> <view class="canvas-item-text" style="-webkit-transform: rotate({{item.turn}});transform: rotate({{item.turn}})"> <text class='canvas-item-text-inner {{scale===1.4?"btnfont":"normal"}}'> {{item.award}}</text> </view> </view> </view> </view> <view class="{{scale===1.4?'btnfont':'normal'}} canvas-btn {{turning?disabled:able}} {{chanceRemain==0?disabled:able}}"></view> </view>
js代码(转盘部分代码):
/** * 抽奖处理函数: */ getLottery: function () { var that = this; if (that.data.count < 5) { //判断用户钻石数量是否大于等于5 that.setData({ isShare: true }) return } //减少钻石数量: this.setData({ count:that.data.count-5, turning:true }); setTimeout(function(){ that.setData({ turning:false }) },4500) var cot = that.data.count // var awardIndex = Math.random() * 6 >>> 0; // 获取奖品配置 var awardsConfig = app.awardsConfig, runNum = 4, awardIndex=0; // if (awardIndex < 2) awardsConfig.chance = false // console.log(awardIndex) //设置概率:随机从数组中抽取一个数,数组中越大的数出现的次数越少,以此实现概率差异 var Parr = [150, 140, 100, 100, 60, 60, 60, 30, 30, 10, 10, 10, 10, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]; var PrandomNum = Math.random() * 78 >>> 0; switch (Parr[PrandomNum]){ case 2: awardIndex = 1 break case 5: awardIndex = 0 break case 10: awardIndex = 2 break case 30: awardIndex = 3 break case 60: awardIndex = 4 break case 100: awardIndex = 5 break case 150: awardIndex = 6 break } console.log("奖品序号:"+awardIndex); // 旋转抽奖 app.runDegs = app.runDegs || 0 console.log('deg', app.runDegs) app.runDegs = app.runDegs + (360 - app.runDegs % 360) + (360 * runNum - awardIndex * (360 / 7)) console.log('deg', app.runDegs) var animationRun = wx.createAnimation({ duration: 4000, timingFunction: 'ease' }) that.animationRun = animationRun animationRun.rotate(app.runDegs).step() that.setData({ animationData: animationRun.export() }) // 记录奖品 var winAwards = wx.getStorageSync('winAwards') || {data:[]} winAwards.data.push(awardsConfig.awards[awardIndex].name + '1个') wx.setStorageSync('winAwards', winAwards) // 中奖提示 setTimeout(function() { if(awardIndex == 0){ that.setData({ isHongbao: true }) hongbao = Math.random().toFixed(4) } else if(awardIndex == 1){ that.togglePopup3() } else if(awardIndex == 2){ wx.showModal({ title: '恭喜', content: '您获得10钻石', showCancel: false }) let timer = setInterval(function(){ that.setData({ count: that.data.count + 1 }) let a = parseInt(that.data.count - cot) if(a==10){ clearInterval(timer) } },50) } else if(awardIndex == 3){ that.setData({ isShare: true }) return } else if(awardIndex == 4){ wx.showModal({ title: '恭喜', content: '您获得宝箱', showCancel: false }) }else if(awardIndex == 5){ wx.showModal({ title: '恭喜', content: '您获得1元红包已存入账户', showCancel: false }) let m = parseFloat(parseFloat(that.data.money) + 1).toFixed(4) that.setData({ money: m }) } else{ wx.showModal({ title: '恭喜', content: '您获得5元红包已存入账户', showCancel: false }) let m = parseFloat(parseFloat(that.data.money) + 5).toFixed(4) that.setData({ money: m }) } }, 4000); },onReady: function (e) { var that = this; wx.getSystemInfo({ success: function(res) { that.setData({ contentHeight:res.windowHeight }); if(res.windowWidth<360){ that.setData({ scale:0.9 }) }else if(res.windowWidth>500){ that.setData({ scale: 1.4 }) } }, }) // getAwardsConfig app.awardsConfig = { count: 50, awards:[ { 'index': 0, 'name': '随机红包'}, { 'index': 1, 'name': '幸运奖'}, { 'index': 2, 'name': '10钻'}, { 'index': 3, 'name': '大量钻石'}, { 'index': 4, 'name': '宝箱'}, { 'index': 5, 'name': '1元红包' }, { 'index': 6, 'name': '5元红包'} ] } // wx.setStorageSync('awardsConfig', JSON.stringify(awardsConfig)) that.setData({ count: app.awardsConfig.count }) // 绘制转盘 var awardsConfig = app.awardsConfig.awards, len = awardsConfig.length, rotateDeg = 360 / len / 2 + 90, html = [], turnNum = 1 / len; // 文字旋转 turn 值 var ctx = wx.createContext(); for (var i = 0; i < len; i++) { // 保存当前状态 ctx.save(); // 开始一条新路径 ctx.beginPath(); // 位移到圆心,下面需要围绕圆心旋转 ctx.translate(150, 150); // 从(0, 0)坐标开始定义一条新的子路径 ctx.moveTo(0, 0); // 旋转弧度,需将角度转换为弧度,使用 degrees * Math.PI/180 公式进行计算。 ctx.rotate((360 / len * i - rotateDeg) * Math.PI/180); // 绘制圆弧 ctx.arc(0, 0, 150, 0, 2 * Math.PI / len, false); // 颜色间隔 if (i % 2 == 0) { ctx.setFillStyle('rgba(255,184,32,.1)'); }else{ ctx.setFillStyle('rgba(255,203,63,.1)'); } // 填充扇形 ctx.fill(); // 绘制边框 ctx.setLineWidth(0.5); ctx.setStrokeStyle('rgba(228,55,14,.1)'); ctx.stroke(); // 恢复前一个状态 ctx.restore(); // 奖项列表 html.push({ turn: i * turnNum + 'turn', lineTurn: i * turnNum + turnNum / 2 + 'turn', award: awardsConfig[i].name, img: awardsConfig[i].img }); }; that.setData({ awardsList: html }); app.globalData.moneyData = { count: that.data.count, money: that.data.money } },
wxss代码:
/* 转盘 */.canvas-container ul, .canvas-container li { margin: 0; padding: 0; list-style: none;}.canvas-container { padding: 2px; margin: 0 auto; position: relative; left: 10rpx; top: 0; width: 330px; height: 310px; border-radius: 50%; /*border: 2px solid #E44025;*/}.canvas-content { box-sizing: content-box; border: 2px solid rgb(255, 224, 151); position: absolute; left: 5px; top: 5px; z-index: 1; display: block; width: 300px; height: 300px; border-radius: inherit; background-clip: padding-box; background-color: rgb(255, 224, 151);}.canvas-element { position: relative; z-index: 1; width: inherit; height: inherit; border-radius: 50%;}.canvas-list { position: absolute; left: 0; top: 0; width: inherit; height: inherit; z-index: 9999;}.canvas-item { position: absolute; left: 0; top: 0; width: 100%; height: 100%; color:rgb(228, 64, 37); font-weight: bold;}.canvas-item-text { position: relative; display: block; margin: 0 auto; padding-top: 10rpx; text-align: center; -webkit-transform-origin: 50% 150px; transform-origin: 50% 150px;}