Вращение колеса фортуны к заданому сектору
Необходимо вращать колесо фортуны к заранее определенным секторам. Есть массив объектов для вывода в дом значений на секторах в колесе фортуны (sectors). Также есть массив выигрышных вариантов (winningSectors). Необходимо вращать колесо к заданным секторам. Колиество попвыток вращения определяется длинной массива winningSectors Ниже код из компонента Vue. Пример на основании которого сверстал колесо можно глянуть здесь https://codepen.io/stoumann/pen/yLWJPMr
Можете подсказать в чем моя ошибка.
<script setup>
import { ref, onMounted } from 'vue'
// Секторы с призами
const sectors = [
{ id: 1, value: 1000, name: 'название' }, // 0 deg
{ id: 2, value: 2000, name: 'название' }, // 45 deg
{ id: 3, value: 3000', name: 'название' }, // 90 deg
{ id: 4, value: 4000, name: 'название' }, // 135 deg
{ id: 5, value: 5000', name: 'название' }, // 180 deg
{ id: 6, value: 6000, name: 'название' }, // 225 deg
{ id: 7, value: 7000, name: 'название' }, // 270 deg
{ id: 8, value: 8000, name: 'название' } // 315 deg
]
const winningSectors = [5, 6] // 180 deg, 225 deg
let currentSpin = 0
const isSpinning = ref(false)
const isModalVisible = ref(false)
const wheelRef = ref(null)
const isButtonDisabled = ref(false)
let previousEndDegree = ref(0)
const emit = defineEmits(['updateModal', 'updateSpinning'])
const extractValue = (value) => {
const match = String(value).match(/[\d.]+/)
return match ? match[0] : ''
}
const spinWheel = () => {
if (currentSpin >= winningSectors.length) {
isButtonDisabled.value = true
return
}
isSpinning.value = true
const spins = Math.floor(Math.random() * 2) + 3 // От 3 до 4 полных оборотов
console.log('spins:', spins)
const sectorsCount = sectors.length
const degreesPerSector = 360 / sectorsCount // Угол одного сектора 360 / 8 = 45
const winningSector = winningSectors[currentSpin] // Текущий выигрышный сектор
console.log('winningSector:', winningSector) // 5, 6
const winningAngle = (winningSector - 1) * degreesPerSector
console.log('winningAngle:', winningAngle)
const totalRotation = 360 * spins + winningAngle
console.log('totalRotation:', totalRotation)
const wheel = wheelRef.value
let animation
if (animation) {
animation.cancel() // Сбросить предыдущую анимацию
}
animation = wheel.animate(
[
{ transform: `rotate(${previousEndDegree.value}deg)` },
{ transform: `rotate(${previousEndDegree.value + totalRotation}deg)` }
],
{
duration: 4000,
direction: 'normal',
easing: 'cubic-bezier(0.440, -0.205, 0.000, 1.130)',
fill: 'forwards',
iterations: 1
}
)
previousEndDegree.value += totalRotation // Обновляем предыдущий угол
setTimeout(() => {
isSpinning.value = false
currentSpin++
if (currentSpin === winningSectors.length) {
isModalVisible.value = true
emit('updateModal', true)
}
emit('updateSpinning', false)
}, 4000)
}
onMounted(() => {
const wheel = wheelRef.value
wheel.style.transform = `rotate(${previousEndDegree.value}deg)`
})
</script>
<template>
<div class="wheel">
<div class="wheel__inner">
<fieldset class="wheel-of-fortune" ref="wheelRef">
<ul>
<li
v-for="sector in sectors"
:key="sector.value"
class="wheel__prize"
:class="`wheel__prize-${sector.id}`"
>
<span class="wheel__prize-group">
<span>
<span>+</span>
<span class="wheel__prize-value">
{{ extractValue(sector.value) }}
</span>
<span v-if="sector.name === 'депозит'">%</span>
</span>
<span class="wheel__prize-text">{{ sector.name }}</span>
</span>
</li>
</ul>
</fieldset>
<div class="wheel__cursor">
<img
src="@/assets/images/cursor.png"
alt="Cursor image"
width="137"
height="107"
/>
</div>
</div>
<button
class="btn-cta"
style="flex-shrink: 0"
@click="spinWheel"
:disabled="isSpinning"
>
<span class="btn-cta__text">Крутить</span>
</button>
</div>
</template>
.wheel-of-fortune {
--_items: 8;
all: unset;
aspect-ratio: 1 / 1;
container-type: inline-size;
direction: ltr;
display: grid;
position: relative;
width: 100%;
position: relative;
background: linear-gradient(0deg, #8133ff, #8133ff),
linear-gradient(45.93deg, #a600f4 30.63%, #5142ff 84.05%);
// padding: 20px;
padding: 1.38888cqi;
padding: calc((20 * 100%) / 430);
// box-shadow: inset 0px 3.30732px 40.9281px #260044;
border-radius: 50%;
&--spinning {
// animation: spin 3s cubic-bezier(0.5, 0, 0.5, 1) forwards;
// animation:
// spin 3s cubic-bezier(0.5, 0, 0.5, 1) forwards,
// wobble 0.5s ease-in-out 3s infinite;
animation:
spin 4s cubic-bezier(0.25, 1, 0.5, 1) forwards,
wobble 1s ease-in-out 4s infinite;
}
&::before {
content: '';
position: absolute;
z-index: 999;
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
box-shadow: inset 0px 3.30732px 40.9281px #260044;
}
& > * {
position: absolute;
}
ul {
all: unset;
clip-path: inset(0 0 0 0 round 50%);
display: grid;
inset: 0;
place-content: center start;
li {
align-content: center;
aspect-ratio: 1 / calc(2 * tan(180deg / var(--_items)));
// clip-path: polygon(0% 10%, 100% 50%, 0% 90%);
clip-path: polygon(0% 0%, 100% 50%, 0% 100%);
display: grid;
font-size: 5.3cqi;
grid-area: 1 / -1;
padding-left: 0.7ch;
rotate: calc(360deg / var(--_items) * calc(var(--_idx) - 1));
transform-origin: center right;
user-select: none;
width: 50cqi;
&:nth-of-type(1) {
--_idx: 1;
}
&:nth-of-type(2) {
--_idx: 2;
}
&:nth-of-type(3) {
--_idx: 3;
}
&:nth-of-type(4) {
--_idx: 4;
}
&:nth-of-type(5) {
--_idx: 5;
}
&:nth-of-type(6) {
--_idx: 6;
}
&:nth-of-type(7) {
--_idx: 7;
}
&:nth-of-type(8) {
--_idx: 8;
}
}
}
}
Написал скрипт для вращения колеса, но не могу определить точную останоку колеса на заданных выигрышных вариантах.