Показать сообщение отдельно
  #9 (permalink)  
Старый 25.04.2014, 23:49
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

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 сек.
Ответить с цитированием