// luckRoll.wxml<view class="canvas-container" style="transform: rotate({{isRotate}}deg)"> <canvas disable-scroll="true" canvas-id='canvas' id="canvas-bg" class='canvas '></canvas> <image src="{{tempFilePath}}"></image></view>
须要定义的数据
// luckRoll.jsdata: { trunBtn: false,//抽奖按钮是否能够点击 itemsNum: 3, //大转盘等分数,可依据后盾配置加载 itemsArc: 0, //大转盘每等分角度 coupons: [],//每个扇形中的文字填充 isRotate: -180, // 初始旋转角度}
创立一个canvas对象,因为它是个组件,所以在传入转盘数据的时候,初始化canvas
properties: { rollOptions: { type: Array, observer(val) { if(val.length > 0) { this.setData({ coupons: val, itemsNum: val.length }) const ctx = wx.createCanvasContext("canvas", this); //创立id为canvas的绘图 this.getGiftList(ctx) } } }},getGiftList(ctx) { let that = this; let itemsArc = 360/that.data.itemsNum that.setData({ itemsArc }, function () { const query = wx.createSelectorQuery().in(that) query.select('#canvas-bg').boundingClientRect() query.exec(function (rect) { w1 = parseInt(rect[0].width / 2); h1 = parseInt(rect[0].height / 2); that.drawRegion(itemsArc, ctx);//每一份扇形的外部绘制。 }) })}
绘制扇形
drawRegion(e, ctx) { let that = this; let itemsArc = e;//每一份扇形的角度 let num = that.data.itemsNum;//等分数量 let itemArr = that.data.coupons.map(item=>item.name);//放文字的数组 for (let i = 0; i < num; i++) { ctx.beginPath(); ctx.moveTo(w1, h1); ctx.arc(w1, h1, w1 - 2, itemsArc * i * Math.PI / 180, (itemsArc + itemsArc * i) * Math.PI / 180);//绘制扇形,默认从第四象限开始画,所以区域编号1的中央为三点钟开始地位 ctx.closePath(); const colorList = ['#7cd8e3', '#ffffff'] ctx.setFillStyle(colorList[i % 2]); ctx.fill(); ctx.save(); ctx.beginPath(); ctx.translate(w1, h1);//将原点移至圆形圆心地位 ctx.rotate((itemsArc * (i + 1 + (num - 2) * 0.25)) * Math.PI / 180);//旋转文字 if (num >= 6) { ctx.setFontSize(18);//设置文字字号大小 } else { ctx.setFontSize(20);//设置文字字号大小 } if (i % 2 == 0) { ctx.setFillStyle("#ffffff");//设置文字色彩 } else { ctx.setFillStyle("#7cd8e3");//设置文字色彩 } ctx.setTextAlign("center");//使文字垂直居中显示 ctx.setTextBaseline("middle");//使文字水平居中显示 if (itemArr[i].length < 7) { ctx.setFontSize(12);//设置文字字号大小 ctx.fillText(itemArr[i], 0, -(h1 * 0.75)); } else if (itemArr[i].length >= 7 && itemArr[i].length <= 10) { let len = Math.ceil(itemArr[i].length / 2) ctx.fillText(itemArr[i].slice(0, len), 0, -(h1 * 0.80)); ctx.fillText(itemArr[i].slice(len), 0, -(h1 * 0.65)); ctx.setFontSize(20);//设置文字字号大小 } else { let mainInfo = itemArr[i].slice(0, 10) + '...' ctx.fillText(mainInfo.slice(0, 6), 0, -(h1 * 0.80)); ctx.fillText(mainInfo.slice(6, 13), 0, -(h1 * 0.65)); ctx.setFontSize(20);//设置文字字号大小 } ctx.restore();//保留绘图上下文,使上一个绘制的扇形保留住。 } ctx.draw(); setTimeout(()=>{ wx.canvasToTempFilePath({ x: 0, y: 0, width: 2 * w1, height: 2 * h1, destWidth: 8 * w1, destHeight: 8 * h1, fileType: 'jpg', quality: 1,//图片的品质,目前仅对 jpg 无效。取值范畴为 (0, 1],不在范畴内时当作 1.0 解决。 canvasId: 'canvas', success: function (res) { var tempFilePath = res.tempFilePath; that.setData({ tempFilePath: res.tempFilePath }) }, fail: function (res) { console.log('---------- ', res) } }, that) },1000) ctx.draw(true);//参数为true的时候,保留以后画布的内容,持续绘制}
wx.canvasToTempFilePath 特地重要,必须将canvas转换为图片在页面上渲染,不然会呈现各种问题,canvas用translateY移出页面显示另外wx.canvasToTempFilePath必须写在setTimeout外面,不然安卓机的图片是黑屏
下面转盘曾经画成,上面就要转动起来
startRoll(index) { let that = this; let turntableRegionId = index+1 let rotate = that.data.isRotate - that.data.isRotate % 360 + (720 - Number(turntableRegionId - 1) * that.data.itemsArc - 0.5 * that.data.itemsArc - 90) // 转动过程写在css动画外面,时长3s that.setData({ isRotate: rotate + 2160 }) let cur = that.data.coupons[index] let isBingo = !!cur.isPrize let award = cur.name that.setData({ isBingo: isBingo, // 是否中奖 award: award // 奖品 }) setTimeout(()=>{ //3S后显示最终后果弹窗 that.setData({ dialogShow: true }) },3000)}
其余细节,我的项目不同再另外写
外围css
.canvas-container { width: 550rpx; height: 550rpx; transition:all 3s ease; position: absolute; top: 45rpx; left: 110rpx; z-index: 1; border-radius: 50%; overflow: hidden;}.canvas{ width: 550rpx; height: 550rpx; display: block; position: fixed; left: -5000px;}