Alexander
Alexander

Reputation: 45

How to write a working timer for animation?

There is an input where I have to set the animation time in seconds. There is a button that starts this animation. But here's how to make the animation work until the specified time ends?

const moveUp = () => {
    const anm = document.querySelector('.animation');
    let position = 0;
    let setPosUp = 350;
    let add = 1;
    let up = setInterval(moveUp, 1);

    function moveUp() {
        if (position == setPosUp) {
            setPosUp = 0;
            add = -1;
            //clearInterval(up);
        }
        else {
            position = position + add;
            anm.style.bottom = `${position}px`;
        }
    }
}

const up = document.getElementById('up');

up.addEventListener('click', moveUp);

let myTime;
let timer = document.getElementById('timer');
let countSeconds;
function startTime() {
    myTime = setInterval(start, 1000);
    document.getElementById('timerr').innerHTML = timer.value;
    countSeconds = timer.value;
}

function start() {
    countSeconds--;
    document.getElementById("timerr").innerHTML = countSeconds;
    if (countSeconds == -1) {
        stop();
        document.getElementById("timerr").innerHTML = "0";
    }
}

function stop() {
    clearInterval(myTime);
}
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css');

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

.wrapper {
    width: 400px;
    margin: 0 auto;
    text-align: center;
}

.container {
    width: 400px;
    height: 400px;
    position: relative;
    background-color: #b8f9f4;
}

.animation {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    background-color: crimson;
    position: absolute;
    margin: auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

button {
    display: flex;
    width: 90px;
    height: 60px;
    border: 0;
    box-sizing: content-box;
    margin: 5px 0;
}

.ball {
    display: flex;
    justify-content: center;
    align-items: center;
}

.fa-solid {
    font-size: 60px;
}

.btn {
    text-align: center;
    padding: 5px;
    cursor: pointer;
    justify-content: center;
    align-items: center;
}

.stop {
    font-size: 18px;
    margin: auto;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

.fa-hand {
    font-size: 24px;
}
<body>
    <div class="wrapper">
        <div class="container">
            <div class="animation"></div>
        </div>
        <input id="timer" type="number" value="0">
        <p id="timerr"> 00 </p>
    </div>
<div class="ball">
        <button id="up" class="btn fa-solid fa-caret-up" onclick="startTime()">
        </button>
    </div>
    <button class="btn stop" onclick="stop()"><i class="fa-solid fa-hand">Stop</i></button>
    <script src="script.js"></script>
</body>

</html>

The Stop button should stop the animation wherever it is and store it in localStorage. I'm just learning Javascript.

Upvotes: 1

Views: 54

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337560

The much easier way to do this, and also far more performant way, is to use CSS animations, not JS.

To do this, create a new keyframe animation and apply it to a class. You can then add this class to your target element when you want the movement to start. You can dynamically control how long the animation will take by setting the animation-duration value.

Also, I'd strongly suggest you review how you name your variables and functions. Give them all meaningful names, and absolutely do not define a new function with the same name as the outer function.

In addition, be consistent with how you retrieve elements from the DOM, ie. stick with querySelector/querySelectorAll or getElementByX, not both, and also be consistent with how you define functions, either use function expressions or function declarations, not both.

Here's a working example with all the above applied to it:

const animationLength = document.querySelector('#timer');
const countdown = document.querySelector('#timerr');
const up = document.querySelector('#up');
const animation = document.querySelector('.animation');
const stop = document.querySelector('.stop');
let countdownInterval;

const startAnimation = () => {
  if (animation.classList.contains('move'))
    return;

  animation.style.animationDuration = animationLength.value + 's';
  animation.classList.add('move');
  startCountdown();
}

const startCountdown = () => {
  countdownInterval = setInterval(updateCountdown, 1000);
  document.getElementById('timerr').innerHTML = timer.value;
  countSeconds = timer.value;
}

const updateCountdown = () => {
  countdown.innerHTML = --countSeconds;
  if (countSeconds <= 0) {
    stopAnimation();
  }
}

const stopAnimation = () => {
  clearInterval(countdownInterval);
  countdown.innerHTML = "0";
  animation.classList.remove('move');
}

up.addEventListener('click', startAnimation);
stop.addEventListener('click', stopAnimation);
animation.addEventListener('animationend', stopAnimation);
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css');
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.wrapper {
  width: 400px;
  margin: 0 auto;
  text-align: center;
}

.container {
  width: 400px;
  height: 400px;
  position: relative;
  background-color: #b8f9f4;
}

.animation {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: crimson;
  position: absolute;
  margin: auto;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  animation-duration: 0;
}

.animation.move {
  animation-name: move_up_return;
}

@keyframes move_up_return {
  0% {
    bottom: 0;
  }
  50% {
    bottom: 350px;
  }
  100% {
    bottom: 0;
  }
}

button {
  display: flex;
  width: 90px;
  height: 60px;
  border: 0;
  box-sizing: content-box;
  margin: 5px 0;
}

.ball {
  display: flex;
  justify-content: center;
  align-items: center;
}

.fa-solid {
  font-size: 60px;
}

.btn {
  text-align: center;
  padding: 5px;
  cursor: pointer;
  justify-content: center;
  align-items: center;
}

.stop {
  font-size: 18px;
  margin: auto;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.fa-hand {
  font-size: 24px;
}
<div class="wrapper">
  <div class="container">
    <div class="animation"></div>
  </div>
  <input id="timer" type="number" value="0">
  <p id="timerr"> 00 </p>
</div>
<div class="ball">
  <button id="up" class="btn fa-solid fa-caret-up"></button>
</div>
<button class="btn stop"><i class="fa-solid fa-hand">Stop</i></button>

Upvotes: 1

Related Questions