Почему в моем коде не работает onanimationend, а addEventListener("animationend") работает?

Я пытаюсь удалить элемент после завершения его анимации затухания. Добавление слушателя к событию animationend работает нормально, а вот назначение обработчика к .onanimationend - нет - функция не срабатывает, когда анимация заканчивается. Почему не работает обработчик on-?

Я запускаю код на FF 48, но проблема возникает и в Chrome 71.

const post = document.querySelector('.post');
const hideButton = post.children[0];

// When hide button is clicked, run fade animation.
hideButton.onclick = function() {
  post.style.animationPlayState = "running";
};

// This function runs
post.addEventListener("animationend", function() {
  console.info('animationend listener running');
  // this.remove();
});

// This function doesn't run
post.onanimationend = function() {
  console.info('onanimationend handler running');
  // this.remove();
};
@keyframes hide {
  0% {
    opacity: 1;
    height: 100%;
    margin: 10px 0;
    padding: 15px;
  }
  75% {
    opacity: 0;
    height: 100%;
    margin: 10px 0;
    padding: 15px;
  }
  100% {
    opacity: 0;
    height: 0px;
    margin: 0px;
    padding: 0px;
  }
}

.post {
  background-color: #80ff00;
  margin: 10px 0;
  padding: 15px;
  animation-name: hide;
  animation-duration: 2s;
  animation-fill-mode: forwards;
  animation-play-state: paused;
}
<div class = "post">
  Post
  <button class = "hide">
    Hide
  </button>
</div>

Конечно. jsfiddle.net/fL4xn7w6/10

Java Broker 28.01.2019 10:23

Я могу воспроизвести проблему в Chrome 71. Элемент выглядит правильно удаленным в FF 56. Похоже, это проблема браузера, а не проблема с вашим кодом.

CertainPerformance 28.01.2019 11:53

Да, на самом деле это проблема браузера. Я отредактировал свой ответ.

user3119231 28.01.2019 12:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
3
2 083
2

Ответы 2

Проверьте версию вашего браузера и сравните с https://caniuse.com/#search=animationend

Firefox v48.0.0 – Java Broker 36 mins ago

Ваш браузер несовместим с animationend

Извините, я недостаточно ясно выразился. Я не пытаюсь запускать 2 обработчика событий одновременно. Я просто привел пример одной функции, которая работает, и другой функции, которая не работает. Для сравнения.

Java Broker 28.01.2019 10:40

onanimationend не работает в моем коде. Даже если я просто что-то записываю в консоль. Но если вместо этого я использую addEventListener, все работает нормально.

Java Broker 28.01.2019 10:56

какой браузер вы используете?

user3119231 28.01.2019 11:01

Фаерфокс v48.0.0

Java Broker 28.01.2019 11:23

Я вижу свойство, когда проверяю свойства DOM, и есть полная поддержка в соответствии с MDN: developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers‌​/…

Java Broker 28.01.2019 12:30

Bro v48 не поддерживает его полностью

user3119231 28.01.2019 12:31

Но последняя версия Chrome, похоже, тоже этого не понимает. Кроме того, по вашей ссылке caniuse FF 5+ делает поддерживает анимацию CSS. Кажется, что происходит что-то более глубокое.

CertainPerformance 28.01.2019 23:13

Может быть что-то для багзиллы.

user3119231 29.01.2019 08:11

Это потому, что Chrome до сих пор не поддерживает, а FF 45 все еще не поддерживает обработчик HTMLElement.onanimationend.
Я не могу сказать для Firefox 45 (кстати, вы должны обновить), но Chrome поддерживает GlobalEventHandler один (window), что объясняет, почему обработчики, подключенные через EventTarget.addEventListener, поймают его.

window.onanimationend = e => {
  // stacksnippet's console also has CSS animations...
  if (e.animationName === 'roundify')
  console.info({ // logging the full event will kill the page
    target: e.target,
    type: e.type,
    animationName: e.animationName
  });
}
#anim {
  width: 100px;
  height: 100px;
  background: #333;
  animation: roundify 2s forwards;
}
@keyframes roundify {
  100% { border-radius: 50%; }
}
<div id = "anim"></div>

Теперь, если вам действительно нужны обработчики HTMLElement и Document, вы вполне можете реализовать их самостоятельно, но учтите, что обычно менять такие DOM-прототипы — плохая идея.

// now we only have our Element's event

anim.onanimationend = e => console.info({ // logging the full event will kill the page
    target: e.target,
    type: e.type,
    animationName: e.animationName
  });
#anim{
  width: 100px;
  height: 100px;
  background: #333;
  animation: roundify 2s forwards;
}
@keyframes roundify {
  100% { border-radius: 50%; }
}
<script>
// This does modify both HTMLElement and Document protoypes,
// should be placed at top most position in the doc possible
(function(){
  if (
    !("onanimationend" in HTMLElement.prototype) &&
    window.onanimationend !== undefined
  ) {
    // will attach the handler on a the Object's `__animationendhandler` property
    const getsetanimationend =   {
      get: function() {
        return this._animationendhandler || null
      },
      set: function(func) {
        this.removeEventListener('animationend', this._animationendhandler);
        if (typeof func !== 'function') {
          this._animationendhandler = null;
          return;
        }
        this._animationendhandler = func;
        this.addEventListener('animationend', func);
      }
    };

    Object.defineProperty(HTMLElement.prototype, 'onanimationend', getsetanimationend);
    Object.defineProperty(Document.prototype, 'onanimationend', getsetanimationend);
  }
})();
</script>
<div id = "anim"></div>

Другие вопросы по теме