elapsedTime для каждой отдельной анимации приходит, не понимаю, как это может помочь.
Давай напишем метод
addClass→promise
для следующего случая:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>…</title>
<style>
.animated {
position: fixed;
top: 0;
left: 50%;
width: 20px;
height: 20px;
background: #f50;
transition: top 5s, left 1s;
}
.move {
top: 0;
left: 0;
}
</style>
</head>
<body>
<div class="animated"></div>
<script>
function parseFloats(string) {
return string.split(",").map(function (string) {
return parseFloat(string) || 0;
});
}
function calcTransitionTime(delay, duration) {
var length = Math.max(duration.length, delay.length),
i = 0, time, maxTime = 0;
while (i < length) {
time = (delay[i] || 0) + (duration[i] || 0);
if (time > maxTime) {
maxTime = time;
}
i++;
}
return Math.ceil(maxTime * 1000);
}
function getTransitionTime(style) {
return calcTransitionTime(
parseFloats(style.transitionDelay),
parseFloats(style.transitionDuration)
);
}
function addClass(element, className) {
return new Promise(function (resolve) {
element.classList.add(className);
var delay = getTransitionTime(getComputedStyle(element));
setTimeout(function () {
resolve(element);
}, delay);
});
}
window.onload = function () {
var el = document.querySelector(".animated");
addClass(el, "move").then(function () {
alert("done");
});
};
</script>
</body>
</html>
http://learn.javascript.ru/play/mdqxkb
Здесь сработает через 1 секунду только один
transitionend
, но максимальное время анимации 5 секунд. Браузер не будет ничего делать для свойства
top
, ни событий, ни reflow. Обещание будет ждать зря 4 секунды. Есть идеи, как определить, что анимация закончилась за 1 секунду?
Изобретать свой CSS парсер как-то не хочется, потому что просто вытащить анимируемое свойство из
document.styleSheets[i].cssRules[j].style[n]
не получится, класс может быть «размазан» по куче
cssRules
.
Тоже самое и с animation:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>…</title>
<style>
.animated {
position: fixed;
top: 0;
left: 50%;
width: 20px;
height: 20px;
background: #f50;
}
.move {
animation: move-top 5s, move-left 1s;
animation-fill-mode: both;
}
@keyframes move-top {
100% {
top: 0;
}
}
@keyframes move-left {
100% {
left: 0;
}
}
</style>
</head>
<body>
<div class="animated"></div>
<script>
function parseFloats(string) {
return string.split(",").map(function (string) {
return parseFloat(string) || 0;
});
}
function calcFiniteAnimationTime(delay, duration, count) {
var length = Math.max(duration.length, delay.length, count.length),
i = 0, time, maxTime = 0;
while (i < length) {
time = (delay[i] || 0) + (duration[i] || 0) * (count[i] || 0);
if (time > maxTime) {
maxTime = time;
}
i++;
}
return Math.ceil(maxTime * 1000);
}
function getFiniteAnimationTime(style) {
return calcFiniteAnimationTime(
parseFloats(style.animationDelay),
parseFloats(style.animationDuration),
parseFloats(style.animationIterationCount)
);
}
function addClass(element, className) {
return new Promise(function (resolve) {
element.classList.add(className);
var delay = getFiniteAnimationTime(getComputedStyle(element));
setTimeout(function () {
resolve(element);
}, delay);
});
}
window.onload = function () {
var el = document.querySelector(".animated");
addClass(el, "move").then(function () {
alert("done");
});
};
</script>
</body>
</html>
http://learn.javascript.ru/play/hOiFcb
Произойдет только одна пара событий
animationstart
и
animationend
, анимация закончится за 1 секунду, но
delay
будет равен 5 сек.