class Turntable {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext(‘2d’);

this.radius = 200;
this.centerX = this.canvas.width / 2;
this.centerY = this.canvas.height / 2;

this.sectorColors = [‘#FF5733’, ‘#FFC300’, ‘#4CAF50’, ‘#3498db’, ‘#9B59B6’, ‘#E74C3C’, ‘#F39C12’, ‘#2C3E50’];
this.sectorPrizes = [‘手机’, ‘电脑’, ‘谢谢惠顾’, ‘拍立得’, ‘谢谢惠顾’, ‘空调’, ‘购物卡’, ‘视频VIP’, ‘护肤品’, ‘蓝牙耳机’, ‘谢谢惠顾’, ‘空气炸锅’]; // 奖项
this.sectorImages = [
‘手机.png’,
‘云端电脑.png’,
‘谢谢参与.png’,
‘相机.png’,
‘谢谢参与.png’,
‘空调.png’,
‘购物好礼场景.png’,
‘暂无会员卡.png’,
‘美妆护肤.png’,
‘耳机.png’,
‘谢谢参与.png’,
‘空气炸锅.png’];
this.spinButton = document.getElementById(‘spinButton’);
this.spinButton.addEventListener(‘click’, () => {
this.startSpin();
const ring1 = document.querySelector(“.ring1”);
const ring2 = document.querySelector(“.ring2”);
ring1.classList.add(“scale-animation”);
ring2.classList.add(“scale-animation”);
});
this.oppositespinButton = document.getElementById(‘oppositespinButton’);
this.oppositespinButton.addEventListener(‘click’, () => {
this.startOppositeSpin();
});

this.sectorImagesData = [];
this.loaded = false;
this.preloadImages();

}

preloadImages() {
let imagesToLoad = this.sectorImages.length;
this.sectorImages.forEach((src, index) => {
const img = new Image();
img.onload = () => {
this.sectorImagesData[index] = img;
imagesToLoad–;
if (imagesToLoad === 0) {
this.loaded = true; //所有图片加载完毕
this.drawWheel();
}
};
img.src = src;
});
}

drawWheel(currentAngle = 0) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
if (!this.loaded) {
return;
}

const numSectors = this.sectorColors.length;
const sectorAngle = (2 * Math.PI) / numSectors;
const usedNumbers = []; //跟踪已经生成的随机数

for (let i = 0; i < numSectors; i++) {
const startAngle = i * sectorAngle;
const endAngle = (i + 1) * sectorAngle;

this.ctx.beginPath();
this.ctx.moveTo(this.centerX, this.centerY);
this.ctx.arc(this.centerX, this.centerY, this.radius, startAngle, endAngle);
this.ctx.closePath();

this.ctx.fillStyle = this.sectorColors[i % this.sectorColors.length];
this.ctx.fill();

// const prizenum = Math.floor(Math.random() * 12);
// const text = this.sectorPrizes[prizenum];
let prizenum;
let text;
do {
prizenum = Math.floor(Math.random() * 12);
} while (usedNumbers.includes(prizenum)); //检查随机数
usedNumbers.push(prizenum);
text = this.sectorPrizes[prizenum];


const textAngle = startAngle + sectorAngle / 2;
const textX = this.centerX + Math.cos(textAngle) * this.radius * 0.8;
const textY = this.centerY + Math.sin(textAngle) * this.radius * 0.8;

this.ctx.save();
this.ctx.translate(textX, textY);
this.ctx.rotate(textAngle + Math.PI / 2);
this.ctx.textAlign = ‘center’;
this.ctx.textBaseline = ‘middle’;
this.ctx.font = ‘20px fantasy’;
this.ctx.fillStyle = ‘#fff’;
this.ctx.fillText(text, 0, 0);
this.ctx.restore();

const image = this.sectorImagesData[usedNumbers[i]]; //从预加载的图片数组中获取图像
const imageX = this.centerX + Math.cos(textAngle) * this.radius * 0.55;
const imageY = this.centerY + Math.sin(textAngle) * this.radius * 0.55;
const imageWidth = 60;
const imageHeight = 60;

this.ctx.save();
this.ctx.translate(imageX, imageY);
this.ctx.rotate(textAngle + Math.PI / 2);
this.ctx.drawImage(image, -imageWidth / 2, -imageHeight / 2, imageWidth, imageHeight);
this.ctx.restore();
}
}

startSpin() {
const numSpins = 2;
const targetSector = Math.floor(Math.random() * this.sectorPrizes.length); // 随机选择一个奖项作为目标扇形
const totalAngle = targetSector * (2 * Math.PI / this.sectorPrizes.length) + (2 * Math.PI) * numSpins;
let currentAngle = 0;
let spinSpeed = 0.08;
let isPaused = false;

const spinAnimation = () => {

if (isPaused) {
return;
}

currentAngle += spinSpeed;
if (currentAngle >= totalAngle) {
const winningSectorIndex = Math.floor(targetSector + numSpins) % this.sectorPrizes.length;
const winningText = this.sectorPrizes[winningSectorIndex];
const winningImage = this.sectorImagesData[winningSectorIndex];
if (winningText === ‘谢谢惠顾’) {
alert(‘很遗憾！您没有中奖’);
} else {
alert(恭喜您中奖！将获得 ${winningText} 一台/张/副);
}
return;
}

this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.save();
this.ctx.translate(this.centerX, this.centerY);
this.ctx.rotate(currentAngle);
this.ctx.translate(-this.centerX, -this.centerY);

this.drawWheel();

this.ctx.restore();

requestAnimationFrame(spinAnimation);
};

requestAnimationFrame(spinAnimation);

spinAnimation();

const stopButton = document.getElementById(“stopButton”);
stopButton.addEventListener(“click”, () => {
isPaused = !isPaused;
});

const speedButton = document.getElementById(“speedButton”);
speedButton.addEventListener(“click”, () => {
spinSpeed = 0.15;
});

}

startOppositeSpin() {
const numSpins = 2;
const targetSector = Math.floor(Math.random() * this.sectorPrizes.length); //随机选择一个奖项作为目标扇形
const totalAngle = targetSector * (2 * Math.PI / this.sectorPrizes.length) + (2 * Math.PI) * numSpins;
let currentAngle = 0;
let spinSpeed = 0.08;
let isPaused = false;

const oppositespinAnimation = () => {
if (isPaused) {
return;
}

currentAngle -= spinSpeed;
if (currentAngle <= -totalAngle) {
const winningSectorIndex = Math.floor(targetSector + numSpins) % this.sectorPrizes.length;
const winningText = this.sectorPrizes[winningSectorIndex];
const winningImage = this.sectorImagesData[winningSectorIndex];
if (winningText === ‘谢谢惠顾’) {
alert(‘很遗憾！您没有中奖’);
} else {
alert(恭喜您中奖！将获得 ${winningText} 一台/张/副);
}
return;
}

this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.save();
this.ctx.translate(this.centerX, this.centerY);
this.ctx.rotate(currentAngle);
this.ctx.translate(-this.centerX, -this.centerY);

this.drawWheel();

this.ctx.restore();

requestAnimationFrame(oppositespinAnimation);
};

oppositespinAnimation();

const stopButton = document.getElementById(“stopButton”);
stopButton.addEventListener(“click”, () => {
isPaused = !isPaused;
});

const speedButton = document.getElementById(“oppositespeedButton”);
speedButton.addEventListener(“click”, () => {
spinSpeed = 0.15;
});
}
}


const turntable = new Turntable(‘gameCanvas’);
turntable.drawWheel();修改代码使得最后弹窗上的奖项文字和垂直水平九十度所指扇形上的文字相符