I’m trying to create a wheelspin component in Vue.js but I have absolutely no clue on how to detect on what sector is currently indicator pointing at.
And how to stop at specific index after the spin is launched ?
WheelSpin component code https://playcode.io/2211878:
<template>
<div class="wof-wrapper">
<div class="wof-indicator"></div>
<div class="wof-container">
<div class="wof-sectors" :class="{ spinning }">
<div
class="sector"
v-for="(item, index) in sectors"
:class="item.code"
:key="item.code"
:style="{
'--i': index,
}"
>
<div class="content">
<div class="inner">
<div class="title">{{ item.code }}</div>
</div>
</div>
</div>
</div>
<div class="wof-center" @click="onBtnSpin">SPIN!</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
/* prettier-ignore */
const sectors = ref([
{ code: 'product1' },
{ code: 'product2' },
{ code: 'product3' },
{ code: 'product4' },
{ code: 'product5' },
{ code: 'product6' },
{ code: 'product7' },
{ code: 'product8' },
{ code: 'product9' },
{ code: 'product10' },
{ code: 'product11' },
{ code: 'product12' },
]);
const spinning = ref(false);
const onBtnSpin = () => {
console.log('Start spinning the wheel');
const randomRotation = Math.floor(Math.random() * (10 - 3 + 1) + 5);
spinning.value = true;
const totalRotation = randomRotation * 360;
let currentRotation = 0;
const sectorElement = document.querySelector('.wof-sectors') as HTMLElement;
const rotateWheel = () => {
if (currentRotation < totalRotation) {
currentRotation += 360;
sectorElement.style.transform = `rotate(${currentRotation}deg)`;
requestAnimationFrame(rotateWheel);
} else {
spinning.value = false;
}
};
rotateWheel();
};
</script>
<style>
.wof-container {
width: 400px;
height: 400px;
border: 2px solid #000;
border-radius: 50%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
.wof-sectors {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
transition: transform 3s cubic-bezier(0.33, 1, 0.68, 1);
}
.wof-sectors .sector {
width: 200px;
height: 200px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
background: #555;
color: #fff;
font-weight: bold;
padding: 10px;
transform: rotate(calc(360deg / 12 * var(--i))) skew(60deg);
transform-origin: 100% 100%;
position: absolute;
top: 0;
left: 0;
position: absolute;
display: flex;
align-items: flex-end;
justify-content: flex-end;
border: 1px solid white;
}
.content {
width: 65%;
transform: skew(-60deg);
position: relative;
left: 20px;
}
.inner {
rotate: 196deg;
bottom: 8px;
position: relative;
display: flex;
align-items: center;
transform-origin: 35%;
}
.title {
pointer-events: none;
font-size: 14px;
text-align: right;
text-transform: uppercase;
}
.q-img {
position: absolute;
width: 30px;
height: auto;
}
.wof-center {
width: 100px;
height: 100px;
color: #fff;
background-color: #000;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
border-radius: 50%;
transition: 0.4s;
position: relative;
transition: 300ms all;
box-shadow: 0 0 0 4px #fff;
display: flex;
align-items: center;
justify-content: center;
}
.wof-center:hover {
box-shadow: 0 0 0 4px #fff, 0 0px 15px 5px rgba(255, 255, 255, 0.6);
cursor: pointer;
}
.wof-center::after {
content: '';
position: absolute;
top: -13px;
border: 10px solid transparent;
border-bottom-color: #fff;
border-top: none;
left: 50%;
margin-left: -10px;
}
</style>
I tried to rotate using css approach but I’m not sure if it’s a good idea.
I have no idea either how to stop the wheel at specific sector.