How to update my die animation so that it starts from where it ended after each random roll?

Viewed 105

I made a die-rolling animation based on switch statement. The die rotates from a start position (you see the front side - red, num 1) and ends up on a random side with the appropriate number on it from the animation.

I would like to make this animation more fluid upon re-rolls. The animation currently starts over suddenly from the original orientation on re-rolls, but I want it to start from the position it ended on its last roll

I tried to use CSS reverse to this animation just after click before next random number generation, but it didn't work.

cube.style.animation = kindaSpin + " 2500ms ease-in-out forwards reverse";

(the code is abbreviated on purpose):

var a = 1;
var cube = document.getElementById("cube");
var num = document.getElementsByClassName("num");
var kindaSpin;
var b; var c; var d; var randomNum; var randomNumStr;

function spin(){

/*RANDOM NUMBER*/
    randomNum = Math.floor(Math.random() * 6) + 1;
    randomNumStr = randomNum.toString();
    for(i = 0; i < num.length; i++) 
        {num[i].style.animation = "";}
    
/*SWITCH*/
        switch(randomNum) {
            case 1:
                kindaSpin = 'one';
                a = "1";
                break;
            case 2:
                kindaSpin = 'two';
                a = "2";
                break;
            case 3:
                kindaSpin = 'three';
                a = "3";
                break;
            case 4:
                kindaSpin = 'four';
                a = "4";
                break;
            case 5:
                kindaSpin = 'five';
                a = "5";
                break;
            case 6:
                kindaSpin = 'six';
                a = "6";
                break;
        }

/*MOVE*/
        cube.style.animationDirection = "normal";
        cube.style.animation = kindaSpin + " 2500ms ease-in-out forwards";

/*NUMBER*/
    setTimeout(() => { document.getElementById("num" + a).style.animation = "fadeIn 2s linear forwards";
; }, 2000); }
@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@800&family=Indie+Flower&family=Teko:wght@500;600;700&display=swap');

:root {
    --size: 50px;
    --half-size: 25px;
    --minus-half-size: -25px;
}
* {
    box-sizing: border-box;
}
.content {
    width: var(--size);
    height: var(--size);
    margin: 50px auto;
    perspective: 1000px;
}
.cube {
    position: relative;
    transform-style:preserve-3d;
    width: var(--size);
    height: var(--size);
    transform: rotateX(-20deg) rotateY(20deg);
}

/*CUBE SIDES*/

.face {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  
    height: var(--size);
    width: var(--size);
    color: aliceblue;

    font-family: 'Teko', sans-serif;     
}
.one{
    background-color: rgba(255, 0, 0, 0.356);
    transform: translateZ(var(--half-size)); /*front*/
}
.two {
    background-color: rgba(0, 128, 0, 0.349);
    transform: translateY(var(--minus-half-size)) rotateX(-270deg) ; /*top*/
}
.three {
    background-color: rgba(0, 0, 255, 0.315);
    transform: translateX(var(--half-size)) rotateY(90deg); /*right*/
}
.four {
    background-color: rgba(255, 255, 0, 0.384);
    transform: translateX(var(--minus-half-size)) rotateY(-90deg); /*left*/
}
.five {    
    background-color: rgba(128, 0, 128, 0.342);
    transform: translateY(var(--half-size)) rotateX(270deg); /*bottom*/
}
.six {    
    background-color: rgba(255, 140, 0, 0.37);
    transform: translateZ(var(--minus-half-size)) rotateY(180deg); /*back*/
}

/*NUMBER*/

.num {
    position:absolute;
    display: block;
    opacity: 0%;
}

/*ANIMATION OF ROTATION*/ 

@keyframes one {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(380deg) rotateZ(360deg);}
}
@keyframes two {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(610deg) rotateY(720deg) rotateZ(20deg);}
}
@keyframes three {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(290deg) rotateZ(360deg);}
}
@keyframes four {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(820deg);}
}
@keyframes five {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(790deg) rotateY(360deg) rotateZ(340deg);}
}
@keyframes six {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(200deg) rotateZ(360deg);}
}
@keyframes fadeIn {
    0%{opacity: 0%;}
    100%{opacity: 100%;}
}
<div class="content" onclick="spin()">
        <div class="cube" id="cube">
            <div class="face one">
                <div class="num" id="num1">1</div> 
            </div>
            <div class="face two">
                <div class="num" id="num2">2</div> 
            </div>
            <div class="face three">
                <div class="num" id="num3">3</div> 
            </div>
            <div class="face four">
                <div class="num" id="num4">4</div> 
                </div>
            <div class="face five">
                <div class="num" id="num5">5</div> 
            </div>
            <div class="face six">
                <div class="num" id="num6">6</div> 
            </div> 
        </div>
    </div>

Here is how the die looks in the final version with gifs: https://cumclavi.cz/cube/ ...it takes some time to load.

1 Answers

I checked my problem once again... and found a little bit longer but valid solution.

I made @keyframes of every spin in reverse order and call it at begining of roll:

cube.style.animation = `${kindaSpin}-back 2500ms ease-in forwards`;

for

@keyframes one-back

...it also became advantege, because I will be able to create each animation different and make more fluent roll.


anyway. If there will be someone who can explain, why cube.style.animation = `${kindaSpin} 2500ms ease-in reverse forwards`; didnt work? Please write me in comments!


var a = 1;
var cube = document.getElementById("cube");
var num = document.getElementsByClassName("num");
var kindaSpin = "one";
var b; var c; var d; var randomNum; var randomNumStr;

function spin(){
   cube.style.animation = kindaSpin + `-back 2500ms ease-in forwards`;

/*RANDOM NUMBER*/
setTimeout(() => { 
    randomNum = Math.floor(Math.random() * 6) + 1;
    randomNumStr = randomNum.toString();
    for(i = 0; i < num.length; i++) 
        {num[i].style.animation = "";}
    
/*SWITCH*/
        switch(randomNum) {
            case 1:
                kindaSpin = 'one';
                a = "1";
                break;
            case 2:
                kindaSpin = 'two';
                a = "2";
                break;
            case 3:
                kindaSpin = 'three';
                a = "3";
                break;
            case 4:
                kindaSpin = 'four';
                a = "4";
                break;
            case 5:
                kindaSpin = 'five';
                a = "5";
                break;
            case 6:
                kindaSpin = 'six';
                a = "6";
                break;
                }
        

/*MOVE*/
        cube.style.animationDirection = "normal";
        cube.style.animation = kindaSpin + " 2500ms ease-in-out forwards";},2500)

/*NUMBER*/
    setTimeout(() => {
  document.getElementById("num" + a).style.animation = "fadeIn 2s linear forwards";}, 5000); 
 }
@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@800&family=Indie+Flower&family=Teko:wght@500;600;700&display=swap');

:root {
    --size: 50px;
    --half-size: 25px;
    --minus-half-size: -25px;
}
* {
    box-sizing: border-box;
}
.content {
    width: var(--size);
    height: var(--size);
    margin: 50px auto;
    perspective: 1000px;
}
.cube {
    position: relative;
    transform-style:preserve-3d;
    width: var(--size);
    height: var(--size);
    transform: rotateX(-20deg) rotateY(20deg);
}

/*CUBE SIDES*/

.face {
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  
    height: var(--size);
    width: var(--size);
    color: aliceblue;

    font-family: 'Teko', sans-serif;     
}
.one{
    background-color: rgba(255, 0, 0, 0.356);
    transform: translateZ(var(--half-size)); /*front*/
}
.two {
    background-color: rgba(0, 128, 0, 0.349);
    transform: translateY(var(--minus-half-size)) rotateX(-270deg) ; /*top*/
}
.three {
    background-color: rgba(0, 0, 255, 0.315);
    transform: translateX(var(--half-size)) rotateY(90deg); /*right*/
}
.four {
    background-color: rgba(255, 255, 0, 0.384);
    transform: translateX(var(--minus-half-size)) rotateY(-90deg); /*left*/
}
.five {    
    background-color: rgba(128, 0, 128, 0.342);
    transform: translateY(var(--half-size)) rotateX(270deg); /*bottom*/
}
.six {    
    background-color: rgba(255, 140, 0, 0.37);
    transform: translateZ(var(--minus-half-size)) rotateY(180deg); /*back*/
}

/*NUMBER*/

.num {
    position:absolute;
    display: block;
    opacity: 0%;
}

/*ANIMATION OF ROTATION*/ 

@keyframes one {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(380deg) rotateZ(360deg);}
}
@keyframes one-back {
    0% {transform: rotateX(700deg) rotateY(380deg) rotateZ(360deg);}
    100% {transform: rotateX(-20deg) rotateY(20deg);}
}

@keyframes two {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(610deg) rotateY(720deg) rotateZ(20deg);}
}
@keyframes two-back {
    0% {transform: rotateX(610deg) rotateY(720deg) rotateZ(20deg);}
    100% {transform: rotateX(-20deg) rotateY(20deg);}
}

@keyframes three {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(290deg) rotateZ(360deg);}
}
@keyframes three-back {
    0% {transform: rotateX(700deg) rotateY(290deg) rotateZ(360deg);}
    100% {transform: rotateX(-20deg) rotateY(20deg);}
}

@keyframes four {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(820deg);}
}
@keyframes four-back {
    0% {transform: rotateX(700deg) rotateY(820deg);}
    100% {transform: rotateX(-20deg) rotateY(20deg);}
}

@keyframes five {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(790deg) rotateY(360deg) rotateZ(340deg);}
}
@keyframes five-back {
    0% {transform: rotateX(790deg) rotateY(360deg) rotateZ(340deg);}
    100% {transform: rotateX(-20deg) rotateY(20deg);}
}

@keyframes six {
    0% {transform: rotateX(-20deg) rotateY(20deg);}
    100% {transform: rotateX(700deg) rotateY(200deg) rotateZ(360deg);}
}
@keyframes six-back {
    0% {transform: rotateX(700deg) rotateY(200deg) rotateZ(360deg);}
    100% {transform: rotateX(-20deg) rotateY(20deg);}
}

@keyframes fadeIn {
    0%{opacity: 0%;}
    100%{opacity: 100%;}
}
<div class="content" onclick="spin()">
        <div class="cube" id="cube">
            <div class="face one">
                <div class="num" id="num1">1</div> 
            </div>
            <div class="face two">
                <div class="num" id="num2">2</div> 
            </div>
            <div class="face three">
                <div class="num" id="num3">3</div> 
            </div>
            <div class="face four">
                <div class="num" id="num4">4</div> 
                </div>
            <div class="face five">
                <div class="num" id="num5">5</div> 
            </div>
            <div class="face six">
                <div class="num" id="num6">6</div> 
            </div> 
        </div>
    </div>

Related