Keyframe animation with javascript timer issues with outer circle rotating around inner circle working sometimes and not other times

Viewed 164

I'm having an Issue with an animation. Basically the way I want it to work is there is three arrows in a circle that go around an inner circle and every 3 seconds it stops for 3 seconds and then continues to rotate. For some reason it keeps skipping the rotation every so often so instead of rotating smoothly it jumps and looks really off. I would really appreciate any help on this and I hope I have explained this well.

HTML

<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<div class="container animation-banner-container">
    <div class="row">
        <div class="col-md-6">
            <div class="outCircle">
                <div class="rotate">
                    <div class="counterrotate">
                    </div>
                </div>
            </div>
        </div>
        <div class="col-md-6"></div>
    </div>
</div>

CSS

.animation-banner-container {
    height: 450px;
    margin-top: -5%;
    overflow: hidden !important;
}

.outCircle  {
    width: 400px;
    height: 400px;
    background: url('https://gdxdesigns.com/wp-content/uploads/2020/12/Outer-Text.png');
    background-size: 400px 400px;
    left: 175px;
    position: absolute;
    top: 50px;
    -moz-border-radius: 100px;
    -webkit-border-radius: 100px;
    border-radius: 100px;
}

.rotate {
    width: 400px;
    height: 400px;
    padding: 100px !important;  
    background: url('https://gdxdesigns.com/wp-content/uploads/2020/12/inner-wheel.png');
    background-size: 400px 400px;
}

.counterrotate {
    width: 400px;
    height: 400px;
    background: url('https://gdxdesigns.com/wp-content/uploads/2020/12/temp-img.png');
    background-size: 400px 400px;
    padding: 150px !important;
    margin: -50%;
}

@keyframes circle-one {
    from { transform: rotateZ(0deg); }
    to { transform: rotateZ(120deg); }
}

@keyframes circle-two {
    from { transform: rotateZ(120deg); }
    to { transform: rotateZ(240deg); }
}

@keyframes circle-three {
    from { transform: rotateZ(240deg); }
    to { transform: rotateZ(360deg); }
}

@keyframes ccircle-one {
    from { transform: rotateZ(360deg); }
    to { transform: rotateZ(240deg); }
}

@keyframes ccircle-two {
    from { transform: rotateZ(240deg); }
    to { transform: rotateZ(120deg); }
}

@keyframes ccircle-three {
    from { transform: rotateZ(120deg); }
    to { transform: rotateZ(0deg); }
}

JS

 var seconds = 3000;
    var tid = setInterval(mycode, seconds);

    var start = 1;
    var slides = 1;

    function mycode(val) {
    if(!val) {
    
        /* Controls the Stop and Start */
        if(start == 1) {
            $(".rotate").css({"animation-play-state": "paused"});
            $(".counterrotate").css({"animation-play-state": "paused"});
            start = 0;

        } else {
            $(".rotate").css({"animation-play-state": "running"});
            $(".counterrotate").css({"animation-play-state": "running"});
         
            if(slides == 1) {
                console.log("Check Slides 1: " + slides);
                $(".rotate").css({"animation": "circle-one 3s infinite linear"});
                $(".counterrotate").css({"animation": "ccircle-one 3s infinite linear"});
                slides = slides + 1;
            } 
            
            else if (slides == 2) {
                console.log("Check Slides 2: " + slides);
                $(".rotate").css({"animation": "circle-two 3s infinite linear"});
                $(".counterrotate").css({"animation": "ccircle-two 3s infinite linear"});
                slides = slides + 1;
            }

            else if (slides == 3) {
                console.log("Check Slides 3: " + slides);
                $(".rotate").css({"animation": "circle-three 3s infinite linear"});
                $(".counterrotate").css({"animation": "ccircle-three 3s infinite linear"});
                slides = 1;
            }
            start = 1;
            
        } // Close else
        /* Close Controls the Stop and Start */

    } else {
        abortTimer();
            tid = setInterval(mycode, seconds);
        }
    }

    function abortTimer() { // to be called when you want to stop the timer
        clearInterval(tid);
    }

JSFiddle

2 Answers

Timing of animations with javascript is always difficult, and often rather impossible to do it in an exact way: if javascript is busy with several other tasks in the meantime, an unpreditable latency can happen. So I wouldn't rely on javascript.

I should suggest to do it with pure css: always in time !

A testpage: http://clba.nl/experiments/rotating-arrow-circle.htm

In this page I've replaced the inner circle by a div with css only; your tmp image is not needed, and can be replaced by a smaller/faster image of the figure only (1.5kB instead of 36kB).

For the background see: CSS Keyframe Animation with Delay Between Iterations on css-tricks.com.

Ok, I managed to get a fresh pair of eyes on this and have found the issue.(Thanks Conor). So basically I just needed to change the "infinite" to "forwards" in the animation so:

From

            if(slides == 1) {
                console.log("Check Slides 1: " + slides);
                $(".rotate").css({"animation": "circle-one 3s infinite linear"});
                $(".counterrotate").css({"animation": "ccircle-one 3s infinite linear"});
                slides = slides + 1;
            } 
            
            else if (slides == 2) {
                console.log("Check Slides 2: " + slides);
                $(".rotate").css({"animation": "circle-two 3s infinite linear"});
                $(".counterrotate").css({"animation": "ccircle-two 3s infinite linear"});
                slides = slides + 1;
            }

            else if (slides == 3) {
                console.log("Check Slides 3: " + slides);
                $(".rotate").css({"animation": "circle-three 3s infinite linear"});
                $(".counterrotate").css({"animation": "ccircle-three 3s infinite linear"});
                slides = 1;
            }

To

            if(slides == 1) {
                console.log("Check Slides 1: " + slides);
                $(".rotate").css({"animation": "circle-one 3s forwards linear"});
                $(".counterrotate").css({"animation": "ccircle-one 3s forwards linear"});
                slides = slides + 1;
            } 
            
            else if (slides == 2) {
                console.log("Check Slides 2: " + slides);
                $(".rotate").css({"animation": "circle-two 3s forwards linear"});
                $(".counterrotate").css({"animation": "ccircle-two 3s forwards linear"});
                slides = slides + 1;
            }

            else if (slides == 3) {
                console.log("Check Slides 3: " + slides);
                $(".rotate").css({"animation": "circle-three 3s forwards linear"});
                $(".counterrotate").css({"animation": "ccircle-three 3s forwards linear"});
                slides = 1;
            }

I have also updated my JSFiddle

Related