Анимация CSS не очищается в JS

#javascript #css

#javascript #css

Вопрос:

Я пишу цифровые часы и хочу создать функцию, которая сдвигает цифры вверх при изменении. Я применяю встроенную анимацию к secondDiv и очищаю ее каждую секунду, но анимация отображается только при загрузке страницы. Я хочу, чтобы она отображалась каждую секунду, поэтому сначала пытаюсь ее очистить. Я пытался secondDiv.style.animation = "" также secondDiv.removeAttribute('style') , но безрезультатно.

Пример Codepen

JS

 const clock = document.querySelector("#clock-body");
const hourDiv = document.querySelector("#hours");
const minuteDiv = document.querySelector("#minutes");
const secondDiv = document.querySelector("#seconds");
const zone = document.querySelector("#zone");

const getDate = () => {
  let date = new Date();
  let hours = date.getHours();
  let minutes = date.getMinutes();
  let seconds = date.getSeconds();

  if (hours > 12) {
    hours = hours - 12;
  }
  if (minutes < 10) {
    minutes = `0${minutes}`;
  }

  if (seconds < 10) {
    seconds = `0${seconds}`;
  }
  hourDiv.textContent = hours;
  minuteDiv.textContent = minutes;
  secondDiv.textContent = seconds;

  secondDiv.style.animation = `0.3s change`;
};

window.setInterval(getDate, 1000);
  

CSS

 @keyframes change {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-30px);
  }
}
  

Что я делаю не так? Как я могу очищать встроенную анимацию каждую секунду, прежде чем она будет применена снова?

Ответ №1:

Удалите стиль сразу после завершения анимации с помощью animationend события. Не дожидаясь следующего цикла.

Вместо: secondDiv.removeAttribute("style");

Использовать

 secondDiv.addEventListener('animationend', () => {
    secondDiv.removeAttribute("style");
});
  

вне вашей getDate функции

Полный пример

 const clock = document.querySelector("#clock-body");
const hourDiv = document.querySelector("#hours");
const minuteDiv = document.querySelector("#minutes");
const secondDiv = document.querySelector("#seconds");
const zone = document.querySelector("#zone");

const getDate = () => {
    
    
    let date = new Date();
    let hours = date.getHours();
    let minutes = date.getMinutes();
    let seconds = date.getSeconds();

    if (hours > 12) {
        hours = hours - 12;
    }
    if (minutes < 10) {
        minutes = `0${minutes}`;
    }

    if (seconds < 10) {
        seconds = `0${seconds}`;
    }
    hourDiv.textContent = hours;
    minuteDiv.textContent = minutes;
    secondDiv.textContent = seconds;
    
    secondDiv.style.animation = `0.3s change`;

    
};

secondDiv.addEventListener('animationend', () => {
    secondDiv.removeAttribute("style");
});

window.setInterval(getDate, 1000);  
 body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background: linear-gradient(#444, #222);
    height: 100vh;
    color: #fff;
}

#clock-body {
    display: flex;
    align-items: center;
    font-size: 2rem;
    font-family: "Courier New", Courier, monospace;
    padding: 2.5rem;
    border: 10px solid #fff;
    border-radius: 20px;
    background: #000;
    box-shadow: 0 8px 30px #212121;

    span {
        font-weight: 300;
        font-size: 3rem;
    }

    #hours,
    #minutes,
    #seconds {
        font-weight: 700;
        font-size: 4rem;
        border-radius: 3px;
    }
}

@keyframes change {
    0% {
        transform: translateY(0);
    }
    100% {
        transform: translateY(-30px);
    }
}  
 <div id="clock-body">
    <div id="hours"></div>
    <span>:</span>
    <div id="minutes"></div>
    <span>:</span>
    <div id="seconds"></div>
    <div id="zone"></div>

</div>  

Комментарии:

1. Ах. Никогда не знал об animationend этом событии. Спасибо!

Ответ №2:

Вот мое решение, оно не идеально, но оно может стать хорошей отправной точкой.

Я использую setTimeout внутри функции вместе со transition свойством css для управления положением и непрозрачностью числа

 const clock = document.querySelector("#clock-body");
const hourDiv = document.querySelector("#hours");
const minuteDiv = document.querySelector("#minutes");
const secondDiv = document.querySelector("#seconds");
const zone = document.querySelector("#zone");

const getDate = () => {
  // secondDiv.removeAttribute("style");
  secondDiv.style.transition = `opacity 0.3s linear`;
  secondDiv.style.transform = `translateY(0px)`;
  secondDiv.style.opacity = `1`;
  let date = new Date();
  let hours = date.getHours();
  let minutes = date.getMinutes();
  let seconds = date.getSeconds();

  if (hours > 12) {
    hours = hours - 12;
  }
  if (minutes < 10) {
    minutes = `0${minutes}`;
  }

  if (seconds < 10) {
    seconds = `0${seconds}`;
  }
  hourDiv.textContent = hours;
  minuteDiv.textContent = minutes;
  secondDiv.textContent = seconds;

  setTimeout(() => {
    secondDiv.style.transition = `all 0.3s linear`;
    secondDiv.style.transform = `translateY(-50px)`;
    secondDiv.style.opacity = `0`;
  }, 500);
};

window.setInterval(getDate, 1000);  
 body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background: linear-gradient(#444, #222);
  height: 100vh;
  color: #fff;
}

#clock-body {
  display: flex;
  align-items: center;
  font-size: 2rem;
  font-family: "Courier New", Courier, monospace;
  padding: 2.5rem;
  border: 10px solid #fff;
  border-radius: 20px;
  background: #000;
  box-shadow: 0 8px 30px #212121;
}

#clock-body span {
  font-weight: 300;
  font-size: 3rem;
}

#clock-body #hours,
#clock-body #minutes,
#clock-body #seconds {
  font-weight: 700;
  font-size: 4rem;
  border-radius: 3px;
}

@keyframes change {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-30px);
  }
}  
 <div id="clock-body">
  <div id="hours"></div>
  <span>:</span>
  <div id="minutes"></div>
  <span>:</span>
  <div class="s-div" id="seconds"></div>
  <div id="zone"></div>

</div>