// luckRoll.wxml
需要定义的数据
// luckRoll.js
data: {
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;
}