208 lines
6.7 KiB
JavaScript
208 lines
6.7 KiB
JavaScript
// 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();
|
||
}
|
||
},
|
||
},
|
||
});
|