I'm trying to create a slot machine... but have a problem on the CSS side. I didn't see this problem while working on 1 slot band, but I got this problem when tried to have 3 slot bands.
It's spinning as well while having 1 slot band. I tried many things to solve this alignment problem but couldn't solve it.
Align Problem:
This to while I have 1 slot band:
my Codes:
var degree1;
degree1 = '505deg';
var root = document.querySelector(':root');
root.style.setProperty('--slot1Rotate',degree1);
var panes = document.querySelectorAll(".slot_item"),
paneSize = 100,
zDepth = paneSize / (2 * Math.tan(Math.PI/panes.length));
for (let index = 0; index < panes.length; index ) {
var xAngle = 360 / panes.length * index;
panes[index].style.transform= "rotateX(" xAngle "deg) translateZ(" zDepth "px)";
}
var machine = document.querySelectorAll('.slot-machine');
var spinBtn = document.querySelector('#spinBtn');
for(let i=0;i<machine.length;i ){
spinBtn.addEventListener('click',function(){
machine[i].classList.add('animation');
});
machine[i].addEventListener('animationend',function() {
machine[i].style.transform = 'rotateX(' degree1 ')';
})
}
:root{
--slot1Rotate: 0;
}
html, body {
height: 100%;
perspective: 600;
background-color: #282a3a;
}
.machine{
top: 25em;
display: flex;
gap: 10px;
align-items: center;
justify-content: center;
position: relative;
}
.slots{
display: flex;
gap: 10px;
justify-content: center;
align-items: center;
}
.slot1{
}
.slot2{
}
.slot3{
}
.slot-machine{
width: 120px;
height: 120px;
list-style: none;
padding: 0;
position:relative;
transform-style: preserve-3d;
}
.animation{
animation-name: x-spin;
animation-duration: 5s;
transition-duration: 3s;
transition-delay: 1s;
}
.slot_item {
height: 100px;
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
width: 100%;
background: rgba(255, 255, 255, 0.832);
backface-visibility: hidden;
}
<div >
<div >
<ul >
<li >1</li>
<li >2</li>
<li >3</li>
<li >4</li>
<li >5</li>
<li >6</li>
<li >7</li>
<li >8</li>
<li >9</li>
<li >10</li>
</ul>
<ul >
<li >1</li>
<li >2</li>
<li >3</li>
<li >4</li>
<li >5</li>
<li >6</li>
<li >7</li>
<li >8</li>
<li >9</li>
<li >10</li>
</ul>
<ul >
<li >1</li>
<li >2</li>
<li >3</li>
<li >4</li>
<li >5</li>
<li >6</li>
<li >7</li>
<li >8</li>
<li >9</li>
<li >10</li>
</ul>
</div>
<button id="spinBtn">Spin</button>
</div>
CodePudding user response:
your bug happens because of one of your for
loop
they have a incrementally value inside rotateX();
,
this is bad because for every panes
there is 10 elements,
and here is the problem!:
the program thinks that the 2second panes
element is starting from index 10,
the third start from index 20
but in reality, we want that the second to start from 0, like the first one,
same logic for the third one.
how I solve that?
- by deleting the panes for loop,
- and insert inside the machines for loop
so for every machine, we can get the machine's panes.
❌ so before the index iteration was 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
✅ now 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
I also refactored your code, to be with
.forEach();
, now is more readable and easy to change.
/* your selectors */
let root = document.querySelector(":root");
let panes = document.querySelectorAll(".slot_item");
let spinBtn = document.querySelector("#spinBtn");
let machines = document.querySelectorAll(".slot-machine");
/* math data */
let degree1 = 310; // before was 505 (309 center correcly)
let paneSize = 100;
let zDepth = paneSize / (2 * Math.tan(Math.PI / panes.length));
root.style.setProperty("--slot1Rotate", `${degree1}deg`);
/* machines logic */
machines.forEach((thisMachine) => {
let thisMachinePanes = thisMachine.querySelectorAll(".slot_item");
/* button clicking logic */
spinBtn.addEventListener("click", () => {
thisMachine.classList.add("animation");
});
/* animation end logic */
thisMachine.addEventListener("animationend", () => {
/* for making animation run every time on click, because you can't add a class if there is the same class before */
thisMachine.classList.remove("animation");
thisMachine.style.transform = `rotateX(${degree1}deg)`;
});
/* panes logic */
thisMachinePanes.forEach((thisPane, index) => {
let xAngle = (360 / panes.length) * index;
thisPane.style.transform = `rotateX(${xAngle}deg) translateZ(${zDepth}px)`;
});
});
:root {
--slot1Rotate: 0;
}
html,
body {
perspective: 600;
background-color: #282a3a;
/* centering */
display: grid;
place-items: center;
height: 100vh;
margin: 0;
}
.machine {
/* top: 25rem; don't center like this */
display: flex;
gap: 10px;
align-items: center;
justify-content: center;
position: relative;
}
.slots {
display: flex;
gap: 10px;
justify-content: center;
align-items: center;
position: relative;
}
.slot-machine {
width: 120px;
height: 120px;
list-style: none;
padding: 0;
position: relative;
transform-style: preserve-3d;
/* default position (from js code) */
transform: rotateX(var(--slot1Rotate));
}
.animation {
animation-name: x-spin;
animation-duration: 5s;
transition-duration: 3s;
transition-delay: 1s;
}
.slot_item {
height: 100px;
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
width: 100%;
background: rgba(255, 255, 255, 0.832);
backface-visibility: hidden;
}
/* added animation keyframes */
@keyframes x-spin {
0% {
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
100% {
/* with the variable changed by js */
transform: rotatex(var(--slot1Rotate));
}
}
.slot1 {}
.slot2 {}
.slot3 {}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div >
<div >
<!-- 1 -->
<ul >
<li >1</li>
<li >2</li>
<li >3</li>
<li >4</li>
<li >5</li>
<li >6</li>
<li >7</li>
<li >8</li>
<li >9</li>
<li >10</li>
</ul>
<!-- 2 -->
<ul >
<li >1</li>
<li >2</li>
<li >3</li>
<li >4</li>
<li >5</li>
<li >6</li>
<li >7</li>
<li >8</li>
<li >9</li>
<li >10</li>
</ul>
<!-- 3 -->
<ul >
<li >1</li>
<li >2</li>
<li >3</li>
<li >4</li>
<li >5</li>
<li >6</li>
<li >7</li>
<li >8</li>
<li >9</li>
<li >10</li>
</ul>
</div>
<button id="spinBtn">Spin</button>
</div>
<script src="./script.js"></script>
</body>
</html>
there is a lot of things to correct,
but at least I solved the aligning issue