我正在制作命运之轮或轮盘赌。一切都运转良好,只是旋转部分,我希望旋转在旋转结束时减慢。我应该在脚本中更改或添加哪里?
let index = Math.floor(Math.random() * this.max)
let rotations = 360 * ((Math.ceil(Math.random() * 10)) + 20) + ((index - 1) / this.max * 360) + (Math.floor(Math.random() * (360/this.max)))
// let rotations = ((index - 1) / this.max * 360)
let seconds = 2 + Math.ceil(Math.random() * 2)
console.log(rotations)
console.log(index)
console.log(this.prizes[index])
const randomAnswer = this.prizes[index]
如何在旋转结束时减慢旋转速度,像命运之轮一样?
轮子是通过将
.circle
类并使用 conic-gradient()
作为背景将其分成 8 个相等的三角形而制成的。然后我在 span
div 中放置了 8 个 .circle
元素(编号)。根据数字,在 .circle
span CSS 中设置准确位置并旋转值,使其面向圆心(这样,获胜的 span 值始终是可读的)。
在圆圈上方,我放了一个向下箭头。这个箭头在定义获胜元素方面起着关键作用。
设置一个随机起点,然后在某个给定时间内将圆跨越。我可以通过调整CSS让它以不同的速度旋转,也可以控制旋转的时间,使其不以匀速旋转。我总是设置过渡持续时间以及计算的随机旋转。
然后,我使用
setTimeout
在从输入字段传入的秒数后停止旋转。之后,我确定哪个 span
元素最接近箭头,并传入我们的获胜元素以显示其值。
// Function to get a current rotation
// Source: https://stackoverflow.com/a/54492696/15167500
function getCurrentRotation(el) {
var st = window.getComputedStyle(el, null);
var tm = st.getPropertyValue("-webkit-transform") ||
st.getPropertyValue("-moz-transform") ||
st.getPropertyValue("-ms-transform") ||
st.getPropertyValue("-o-transform") ||
st.getPropertyValue("transform") ||
"none";
if (tm != "none") {
var values = tm.split('(')[1].split(')')[0].split(',');
/*
a = values[0];
b = values[1];
angle = Math.round(Math.atan2(b,a) * (180/Math.PI));
*/
//return Math.round(Math.atan2(values[1],values[0]) * (180/Math.PI)); //this would return negative values the OP doesn't wants so it got commented and the next lines of code added
var angle = Math.round(Math.atan2(values[1],values[0]) * (180/Math.PI));
return (angle < 0 ? angle + 360 : angle); //adding 360 degrees here when angle < 0 is equivalent to adding (2 * Math.PI) radians before
}
return 0;
}
// Function to get a random rotation between 0 and 360 degrees
function getRandomRotation() {
return Math.random() * 360;
}
// Function to get a rotation to .circle span
function getRotationToSpan(number) {
return 360 / 8 * Math.abs(number - 7);
}
// Create Spin to Element
const useSpin = (container) => {
const circle = container.querySelector('.circle');
// from the test, I change the starting rotation from 0
// default start number 7, now I set start number to Random(1, 7)
const randomStartNumber = Math.floor(Math.random() * 7) + 1; // between 1 and 7
circle.style.transform = `rotate(${getRotationToSpan(randomStartNumber)}deg)`;
const arrow = container.querySelector('.arrow');
let latestRotation = getCurrentRotation(circle);
// Function to handle the spinning animation
function spin(button = undefined) {
// Config
const direction = 1; // 1 (left) or -1 (right)
const duration = 10;
const fakeSpinCount = 4;
// Calculate rotation degree
const randomRotation = getRandomRotation();
const fakeSpinRotation = fakeSpinCount * 360;
const nextRotation = (randomRotation + fakeSpinRotation) * direction;
latestRotation += nextRotation;
// If spin() call with HTML.Element, set disabled status
if (button) {
button.disabled = 'disabled';
}
// Set animation to circle; Start spin by rotate()
circle.style.transition = `transform ${duration}s cubic-bezier(0.25, 0.1, 0.25, 1)`;
circle.style.transform = `rotate(${latestRotation}deg)`;
// Wait, while transform is running (duration)
setTimeout(() => {
// Remove animation from circle
circle.style.transition = '';
// If spin() call with HTML.Element, remove disabled status
if (button) {
button.removeAttribute('disabled');
}
// Calculate the closest number to the arrow's rotation
const spans = circle.querySelectorAll('span');
const arrowRotation = -arrow.getBoundingClientRect().top + latestRotation;
let minDifference = Infinity;
let closestNumber;
spans.forEach((span) => {
const spanRotation = -span.getBoundingClientRect().top + latestRotation;
const difference = Math.abs(spanRotation - arrowRotation);
if (difference < minDifference) {
minDifference = difference;
closestNumber = span.textContent;
}
});
console.log('Closest number:', closestNumber);
}, duration * 1000);
}
return {
spin,
}
}
const { spin } = useSpin(document.querySelector('.spin-container'));
.spin-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.circle {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background: conic-gradient(from -22.5deg, #4ab2e5 0, #4ab2e5 12.5%, #001b66 12.5%, #001b66 25%, #4ab2e5 25%, #4ab2e5 37.5%, #001b66 37.5%, #001b66 50%, #4ab2e5 50%, #4ab2e5 62.5%, #001b66 62.5%, #001b66 75%, #4ab2e5 75%, #4ab2e5 87.5%, #001b66 87.5%, #001b66 100%);
font-size: 24px;
color: #ffffff;
}
.circle span {
position: absolute;
top: 50%;
left: 50%;
width: 1.5em;
height: 1.5em;
line-height: 1.5em;
text-align: center;
border-radius: 50%;
transform: translate(-50%, -50%) rotate(calc(45deg * var(--n))) translate(80px) rotate(90deg);
}
.circle span:nth-child(odd) {
background-color: #4ab2e5;
}
.circle span:nth-child(even) {
background-color: #001b66;
}
.arrow {
width: 0;
height: 0;
border: 15px solid transparent;
border-top-color: #000;
}
.prize {
font-size: 16px;
font-weight: bold;
color: #000;
}
<button onclick="spin(this)">SPIN</button>
<div class="spin-container">
<div class="prize">Prize</div>
<div class="arrow"></div>
<div class="circle">
<span style="--n: 0;">1</span>
<span style="--n: 1;">2</span>
<span style="--n: 2;">3</span>
<span style="--n: 3;">4</span>
<span style="--n: 4;">5</span>
<span style="--n: 5;">6</span>
<span style="--n: 6;">7</span>
<span style="--n: 7;">8</span>
</div>
</div>