@AfterGen

Как корректно обрабатывать события метода animate в Web Animation API?

В примере я обрабатываю 3 события: mouseenter скейлит элемент, mousemove разворачивает и mouseleave сбрасывает в исходный вид. Взгляните на видео с проблемой. В конце видео элемент не возвращается в исходное положение. Я заметил, что чаще это происходит, если очень-очень быстро триггерить событие mousemove в пределах элемента. Реже может происходить и в случае быстрого чередования mouseenter-mouseleave.

Если убрать очистку кадров overAnimation.cancel() в обработчике onLeave, это решает проблему. Но ломается другая анимация в моем проекте, навешанная на родительский Vue-компонент <transition-group>, поэтому очистку нужно оставить. Как при таком условии корректно обработать события?

<div class="item"></div>
const itemRef = document.querySelector('.item')
let overAnimation = null

itemRef.addEventListener('mouseleave', (e) => {
    overAnimation = itemRef.animate([
        {
            transform: 'none',
        }
    ], {duration: 1000, fill: 'forwards'})

    overAnimation.onfinish = () => {
        overAnimation.cancel()
    }
})

itemRef.addEventListener('mousemove', (e) => {
    const x = e.offsetX
    
    overAnimation = itemRef.animate([
        {
            transform: `scale(1.6) rotate(${x}deg)`,
        }
    ], {duration: 1000, fill: 'forwards'})
})

itemRef.addEventListener('mouseenter', (e) => {
    overAnimation?.cancel()

    overAnimation = itemRef.animate([
        {
            transform: 'scale(1.6)',
        }
    ], {duration: 1000, fill: 'forwards'})
})
  • Вопрос задан
  • 18 просмотров
Пригласить эксперта
Ответы на вопрос 1
RusPOPsy
@RusPOPsy
Говорила мама, учи математику ...
Порядок срабатывания эвентов не гарантирует, что порядок запуска анимации будет такой же.
Не знаю как понятнее объяснить ...

Но оставлю тут исправный вариант )
const itemRef = document.querySelector('.item')
let move = (e) => {
    const x = e.offsetX
    itemRef.animate([{
        transform: `scale(1.6) rotate(${x}deg)`,
    }], {duration: 1000, fill: 'forwards'})
}

itemRef.addEventListener('mouseleave', (e) => {
    itemRef.removeEventListener('mousemove', move)
    itemRef.animate([{
        transform: 'none',
    }], {duration: 1000, fill: 'forwards'})
})

itemRef.addEventListener('mouseenter', (e) => {
    itemRef.addEventListener('mousemove', move)
})


P/S
что там с этим overAnimation.cancel() - не знаю ... оно точно надо?
анимация отмененная после завершения что то меняет?
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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