Отказ от ответственности : Я не думаю, что jQuery важен для ответа на этот вопрос, и это ухудшило бы как нагрузку, так и производительность во время выполнения, если бы другие увидели этот код после просмотра этого ответа.Итак, я отвечу с помощью ванильного JavaScript, чтобы помочь как можно большему количеству людей с этим, но если вы хотите использовать jQuery, вы все равно можете применять те же понятия.
Ответ: Нетt очередь анимации, но вы можете создать свою собственную.
Например, вы можете связать данные об анимации с целевым элементом, используя замыкание, и / или Map
(В приведенном ниже фрагменте кода я на самом деле использовал WeakMap
в попытке помочь в сборке мусора).Если вы сохраняете состояния анимации как true
, когда они завершены, вы можете проверить и в конечном итоге запустить другой обратный вызов, когда все они true
, или отправить свое собственное событие.Я использовал пользовательский подход к событиям, потому что он более гибкий (способен добавлять несколько обратных вызовов).
Следующий код должен дополнительно помочь вам избежать ожидания ВСЕХ анимаций в тех случаях, когда вы на самом деле заботитесь только о паре конкретных,Он также должен позволять обрабатывать события анимации несколько раз и для нескольких отдельных элементов (попробуйте запустить фрагмент и щелкнуть несколько раз по полям)
const addAnimationEndAllEvent = (() => {
const weakMap = new WeakMap()
const initAnimationsObject = (element, expectedAnimations, eventName) => {
const events = weakMap.get(element)
const animationsCompleted = {}
for (const animation of expectedAnimations) {
animationsCompleted[animation] = false
}
events[eventName] = animationsCompleted
}
return (element, expectedAnimations, eventName = 'animationendall') => {
if (!weakMap.has(element)) weakMap.set(element, {})
if (expectedAnimations) {
initAnimationsObject(element, expectedAnimations, eventName)
}
// When any animation completes...
element.addEventListener('animationend', ({ target, animationName }) => {
const events = weakMap.get(target)
// Use all animations, if there were none provided earlier
if (!events[eventName]) {
initAnimationsObject(target, window.getComputedStyle(target).animationName.split(', '), eventName)
}
const animationsCompleted = events[eventName]
// Ensure this animation should be tracked
if (!(animationName in animationsCompleted)) return
// Mark the current animation as complete (true)
animationsCompleted[animationName] = true
// If every animation is now completed...
if (Object.values(animationsCompleted).every(
isCompleted => isCompleted === true
)) {
const animations = Object.keys(animationsCompleted)
// Fire the event
target.dispatchEvent(new CustomEvent(eventName, {
detail: { target, animations },
}))
// Reset for next time - set all animations to not complete (false)
initAnimationsObject(target, animations, eventName)
}
})
}
})()
const toggleAnimation = ({ target }) => {
target.classList.toggle('being-animated')
}
document.querySelectorAll('.animatable').forEach(element => {
// Wait for all animations before firing the default event "animationendall"
addAnimationEndAllEvent(element)
// Wait for the provided animations before firing the event "animationend2"
addAnimationEndAllEvent(element, [
'animateOpacity',
'animatePosition'
], 'animationend2')
// Listen for our added "animationendall" event
element.addEventListener('animationendall', ({detail: { target, animations }}) => {
console.log(`Animations: ${animations.join(', ')} - Complete`)
})
// Listen for our added "animationend2" event
element.addEventListener('animationend2', ({detail: { target, animations }}) => {
console.log(`Animations: ${animations.join(', ')} - Complete`)
})
// Just updated this to function on click, so we can test animation multiple times
element.addEventListener('click', toggleAnimation)
})
.animatable {
margin: 5px;
width: 100px;
height: 100px;
background: black;
}
@keyframes animateOpacity {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
@keyframes animatePosition {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(0, 15px, 0);
}
}
@keyframes animateRotation {
100% {
transform: rotate(360deg);
}
}
.animatable.being-animated {
animation:
animateOpacity 1s ease 0s forwards,
animatePosition 1.5s ease 0s forwards,
animateRotation 2s ease 0s forwards;
}
<div class="animatable"></div>
<div class="animatable"></div>