@stan288

Почему transitionend ломается если быстро нажимать на кнопку?

https://codepen.io/stn28/pen/RwYyBBx

Небольшая анимация кнопки при клике. Если быстро кликать 10-15 секунд, transitionend перестает свитчить классы на кнопке. Как сделать такой код надежнее, чтобы данная проблема не возникала? (только без setTimeout, это уже костыли тут их применять) И почему такое странное поведение? Действительно интересно. Или вообще делать такие анимации подобным образом неправильно? Через псевдоклассы, например :active анимация проигрывается не полностью если клик быстрый, по-этому приходится использовать js

<script>
  function translateY(e) {
  e.classList.add('translate');
  e.addEventListener('transitionend', function() {
    e.classList.remove('translate');
  }, { once: true });
}

</script>
<button onclick="translateY(this)">Click me</button>


button {
  border: 1px solid;
  background-color: #eee;
  display: inline-block;
  transition: transform 0.1s ease-in-out;
}
.translate {
  transform: translateY(5px) scale(0.9);
}
  • Вопрос задан
  • 96 просмотров
Пригласить эксперта
Ответы на вопрос 4
@StepsOnes
Проблема заключается в том, что при быстрых кликах на кнопку, очередные вызовы функции `translateY()` начинаются еще до того, как завершится предыдущая анимация (и соответственно, "transitionend" не успевает сработать). Это приводит к созданию множества слушателей события transitionend на одном элементе, что затрудняет правильную работу анимации при последующих кликах.

Для решения этой проблемы можно добавить проверку наличия класса "translate" на элементе, перед добавлением его на кнопку. Если класс уже присутствует, то следует пропустить выполнение функции и не добавлять новый слушатель события transitionend:

function translateY(e) {
  if (!e.classList.contains('translate')) {
    e.classList.add('translate');
    e.addEventListener('transitionend', function handler() {
      e.classList.remove('translate');
      e.removeEventListener('transitionend', handler);
    });
  }
}


В этом коде мы проверяем, не содержится ли наш элемент класса "translate" перед добавлением этого класса. Далее, если класса нет, то мы добавляем слушатель события transitionend, и при завершении анимации удаляем слушатель и удаляем класс "translate" с элемента.

Такой подход обеспечивает правильную работу анимации при быстрых кликах на кнопку.

Отмечу, что в целом, использование js для реализации простой анимации как в данном примере может считаться избыточным. В большинстве случаев, на такие анимации можно обойтись использованием только css (как вы и отметили, через псевдоклассы, например :active).
Ответ написан
Комментировать
JustKappaMan
@JustKappaMan
Frontend, backend, desktop. Всего понемногу.
По одной из первых ссылок в Гугле советуют заменить add() и remove() на toogle(). Попробовал - мне помогло. Даже нажатие кнопкой двойного клика не "вешает" кнопку.
Ответ написан
imko
@imko
Senior Scratch Developer
А если keyframes? Из скрипта полный доступ к ним есть
Забираешь анимации висящие на элементе
Запускаешь и останавливаешь по желанию)
Ответ написан
Комментировать
@lilkan
Начинающий разработчик
https://codesandbox.io/s/determined-banach-qoktdi?...

вкратце, нужно было поиграться с focus/active в css, полностью без js, и использовать animations
тут могут возникнуть проблемы c ie11
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы