колесо фортуны на JS + php
Возникла проблема при разработке колеса фортуны.
Сейчас на колесе неправильно отображается секция с призом.
То есть - на секцию должна показать стрелочка, которая отрисована в css.
Как рассчитать так, чтобы после отработки алгоритма на сервере, к клиенту пришёл не только в виде сообщения, как сейчас, реализовано, но и отобразился на колесе верно?
Код js
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const spinButton = document.getElementById('spinButton');
const result = document.getElementById('result');
const prizeImg = document.getElementById('prize-img');
const prizeImageDiv = document.getElementById('prize-image');
let isSpinning = false;
let remainingSpins = parseInt(document.getElementById('remainingSpins').textContent);
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = centerX;
const numberOfSegments = allPrizes.length;
const anglePerSegment = (2 * Math.PI) / numberOfSegments;
// Смещение, чтобы остановиться в середине сегмента
const offsetAngle = anglePerSegment / 2;
const backgroundImage = new Image();
backgroundImage.src = '/images/wheel-background.png';
backgroundImage.onload = () => {
drawWheel(allPrizes);
};
backgroundImage.onerror = () => {
console.error('Ошибка при загрузке фонового изображения');
};
function drawWheel(prizes, currentAngle = 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
for (let i = 0; i < numberOfSegments; i++) {
const startAngle = currentAngle + i * anglePerSegment;
const endAngle = startAngle + anglePerSegment;
ctx.beginPath();
ctx.moveTo(centerX, centerY);
ctx.arc(centerX, centerY, radius, startAngle, endAngle);
ctx.fillStyle = i % 2 === 0 ? 'rgba(251, 197, 49, 0.3)' : 'rgba(243, 156, 18, 0.3)';
ctx.fill();
ctx.closePath();
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(startAngle + anglePerSegment / 2);
ctx.textAlign = "right";
ctx.fillStyle = "#2c3e50";
ctx.font = 'bold 11px sans-serif';
ctx.fillText(prizes[i].prize_name, radius - 20, 10); // Отображаем название приза
ctx.restore();
}
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
ctx.lineWidth = 5;
ctx.strokeStyle = '#F9A602';
ctx.stroke();
ctx.closePath();
drawArrow();
}
// Функция для отрисовки стрелки
function drawArrow() {
const arrowSize = 30;
ctx.beginPath();
ctx.moveTo(centerX - arrowSize, centerY - radius - arrowSize - 10);
ctx.lineTo(centerX + arrowSize, centerY - radius - arrowSize - 10);
ctx.lineTo(centerX, centerY - radius - 10);
ctx.closePath();
ctx.fillStyle = '#F9A602';
ctx.fill();
}
// Функция для вычисления сегмента, который остановился в верхней части (на стрелке)
function getWinningSegment(currentAngle) {
const adjustedAngle = (currentAngle % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI);
const winningIndex = Math.floor((adjustedAngle / anglePerSegment) % numberOfSegments);
return winningIndex;
}
// Функция для вращения колеса
function spinWheel() {
if (isSpinning || remainingSpins <= 0) return;
drawWheel(allPrizes, 0);
isSpinning = true;
const rotations = Math.floor(Math.random() * 5) + 3;
const randomSegment = Math.floor(Math.random() * numberOfSegments);
// Финальный угол будет рассчитан так, чтобы указатель остановился на середине выбранного сегмента
const finalAngle = randomSegment * anglePerSegment + offsetAngle;
const totalAngle = rotations * 2 * Math.PI + finalAngle;
let currentAngle = 0;
const spinTime = 5000;
const startTime = Date.now();
function animate() {
const elapsed = Date.now() - startTime;
const easeOut = t => t * (2 - t);
currentAngle = easeOut(elapsed / spinTime) * totalAngle;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.translate(centerX, centerY);
ctx.rotate(currentAngle);
ctx.translate(-centerX, -centerY);
drawWheel(allPrizes, currentAngle);
ctx.restore();
if (elapsed < spinTime) {
requestAnimationFrame(animate);
} else {
isSpinning = false;
// Отправка запроса на сервер для обновления информации и получения результата
fetch('spin.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ action: 'spin' }) // Тело запроса может быть полезным, если нужно передавать дополнительные данные
})
.then(response => response.json())
.then(data => {
console.log('Ответ от сервера:', data);
if (data.status === 'success') {
result.textContent = `Вы выиграли: ${data.real_prize}!`;
prizeImg.src = data.prize_image_url;
prizeImageDiv.style.display = 'block';
// Обновляем количество оставшихся прокруток
console.log('Старое значение remainingSpins:', remainingSpins);
remainingSpins = data.remaining_spins;
console.log('Новое значение remainingSpins:', remainingSpins);
document.getElementById('remainingSpins').textContent = remainingSpins;
if (remainingSpins <= 0) {
spinButton.disabled = true;
}
} else {
alert(data.message);
}
})
.catch(error => {
console.error('Ошибка получения результата от сервера:', error);
isSpinning = false; // Разрешаем повторить попытку, если был сбой
});
}
}
animate();
}
spinButton.addEventListener('click', spinWheel);