// mycomponent/DTurntable/DTurntable.js // let angle = 0; // let duration = 0; Component({ /** * 组件的属性列表 */ properties: { prize: { type: Array, value: [], //* 奖品,数组类型,格式 [ { text:"aaa",image:"图片地址",color:"随css颜色" },... ] 当数组后面的元素的没有color时会循环 前面的color }, start: { type: Boolean, value: false, //* 是否开始旋转,会监听这个变量,为true时旋转 }, lottery: { type: Number, value: 0, //* 中奖的 索引号 相对于prize }, minTurns: { type: Number, value: 3, //* 旋转最少 多少圈 }, maxTurns: { type: Number, value: 5, //* 旋转最多 多少圈 }, minDuration: { type: Number, //* transition 最小时间 */ value: 7, //* 秒级 }, maxDuration: { type: Number, //* transition 最大时间 会随机从 minDuration 和maxDuration中选择一个随机数 */ value: -1, //* 秒级 }, debug: { type: Boolean, //* 调试模式,会隐藏canvas和显示奖品index value: false, }, angle: { type: Number, //* 距离中奖区域边距 例如中奖区域是 15-30度 指针落在区域会是 15+angle的度数 至 30-angle的度数之间。传入是-1的话就是正中心 value: -1, }, infinite: { type: Boolean, //* 无限滚动。当突然变为false会开始正常滚动 value: false, }, }, ready() { if (this.data.debug === false) { this.drawCircle(); } let prize = this.data.prize; for (let index = 0; index < prize.length; index++) { const prizeItem = prize[index]; prizeItem["angle"] = (360 / prize.length) * index + 180 / prize.length; } this.fillLatticeColor(); prize = prize.reverse(); this.setData({ itemAngle: 360 / this.data.prize.length, prize, }); }, /** * 组件的初始数据 */ data: { lotteryRotateAngle: 0, transitionDuration: 0, transitionFunction: "linear", spinning: false, itemAngle: 0, latticeColors: [], }, /** * 组件的方法列表 */ methods: { drawCircle() { const query = this.createSelectorQuery(); query .select("#lotteryCanvas") .fields({ node: true, size: true }) .exec((res) => { let latticeColors = this.data.latticeColors; if (latticeColors.length == 0) { latticeColors = this.generateColors(["#fff", "#feb446"], this.data.prize.length); } const borderColor = "transparent"; const prizeLength = latticeColors.length; const canvasNode = res[0].node; const screenDPR = wx.getSystemInfoSync().pixelRatio; const canvasContext = canvasNode.getContext("2d"); const canvasW = res[0].width * screenDPR; const canvasH = res[0].height * screenDPR; canvasNode.width = canvasW; canvasNode.height = canvasH; canvasContext.translate(0, canvasH); canvasContext.rotate((-90 * Math.PI) / 180); const outRadius = canvasW / 2; const innerRadius = 0; const baseAngle = (Math.PI * 2) / prizeLength; canvasContext.clearRect(0, 0, canvasW, canvasH); canvasContext.strokeStyle = borderColor; // 设置画图线的颜色 for (let index = 0; index < prizeLength; index++) { const angle = index * baseAngle; canvasContext.fillStyle = latticeColors[index]; canvasContext.beginPath(); canvasContext.arc(canvasW * 0.5, canvasH * 0.5, outRadius, angle, angle + baseAngle, false); canvasContext.arc(canvasW * 0.5, canvasH * 0.5, innerRadius, angle + baseAngle, angle, true); canvasContext.stroke(); //开始连线 canvasContext.fill(); //填充颜色 canvasContext.save(); //保存当前环境的状态 } }); }, startSpinning() { if (this.data.spinning) { return; } const borderStart = this.data.lottery * this.data.itemAngle; //* 中奖区域开始度数 const borderEnd = borderStart + this.data.itemAngle; //* 中奖区域结束度数 const randomTurns = this.randomRange(this.data.minTurns, this.data.maxTurns); //* 随机圈数 let maxDurationSeconds = randomTurns; if (this.data.maxDuration !== -1) { maxDurationSeconds = this.data.maxDuration; } const rotateTransitionDurationSeconds = this.randomRange(this.data.minDuration, maxDurationSeconds); //* 随机 过渡时间 每圈时间=randomTurns / rotateTransitionDurationSeconds let angle = randomTurns * 360; if (this.data.angle === -1) { angle += borderStart + this.data.itemAngle / 2; //* 奖品正中心 } else { angle += this.randomRange(borderStart, borderEnd); //* 随机度数 圈数*360 也就是转多少圈, 加上后面的指定度数 就停在指定礼品区域 } this.setData( { lotteryRotateAngle: 0, transitionDuration: 0, spinning: true, }, () => { setTimeout(() => { this.setData({ lotteryRotateAngle: angle, transitionDuration: rotateTransitionDurationSeconds, }); setTimeout(() => { this.setData({ spinning: false, }); this.triggerEvent("end", { duration: rotateTransitionDurationSeconds, angle, turns: randomTurns, angleRange: { start: borderStart, end: borderEnd, }, itemAngle: this.data.itemAngle, }); }, rotateTransitionDurationSeconds * 1000); }, 500); } ); }, randomRange(lowerValue, upperValue) { return Math.floor(Math.random() * (upperValue - lowerValue + 1) + lowerValue); }, fillLatticeColor() { let latticeColors = []; this.data.prize.forEach((prizeItem) => { if (prizeItem.color) { latticeColors.push(prizeItem.color); } }); if (latticeColors.length > 0) { latticeColors = this.generateColors(latticeColors, this.data.prize.length); } this.setData({ latticeColors, }); }, generateColors(initColors = [], needLength) { let initLength = initColors.length; for (let index = initColors.length; index < needLength; index++) { initColors.push(initColors[index - initLength]); } return initColors; }, }, observers: { start(newV) { if (newV === true) { this.startSpinning(); } }, }, });