Определить, является ли свойство анимируемым при переходе CSS3? - PullRequest
5 голосов
/ 13 января 2011

Список свойств, которые можно анимировать с помощью перехода CSS3, не согласован между браузерами и может изменяться в новых версиях браузера.Например, -moz-transform не может быть анимирован с помощью -moz-transition в FF3.6, но он есть в FF4.

Итак, есть ли способ определить в JavaScript, является ли определенное свойство анимируемым?Я не хотел бы использовать сниффинг пользовательского агента, поскольку он ненадежен.

Заранее спасибо!

Ответы [ 2 ]

9 голосов
/ 27 июня 2012

Да, есть способ.Демонстрация следует, объяснение ниже.Есть несколько очень важных предостережений , поэтому обязательно прочитайте.

Следующий код проверит, может ли браузер анимировать между двумя значениями.

Код

jsFiddle demo .

/*
@param property  The property to test.
@param from      A valid starting value for the animation.
@param to        A valid ending value for the animation.
@param [element] The element to test with. (Required for testing
                 properties with prerequisites, e.g. "top" requires
                 non-static position.)
*/
function isAnimationSupported(property, from, to, element) {
    var doc = document.documentElement,
        style = doc.appendChild(document.createElement("style")),
        rule = [
                'capTest{',
                    '0%{',   property, ':', from, '}',
                    '100%{', property, ':', to,   '}',
                '}'
               ].join(''),
        propCamel = property.toCamelCase(),
        prefixes = 'moz ms o webkit '.split(' '), // Unprefixed last, see comments.
        prefixCount = prefixes.length,
        canAnimate = false;

    element = doc.appendChild((element)
            ? element.cloneNode(false)
            : document.createElement('div'));

    // Detect invalid start value. (Webkit tries to use default.)
    element.style[propCamel] = to;

    // Iterate through supported prefixes.
    for (var i = 0; i < prefixCount; i++) {

        // Variations on current prefix.
        var prefix  = prefixes[i],
            hPrefix = (prefix) ? '-' + prefix + '-' : '',
            uPrefix = (prefix) ? prefix.toUpperCase() + '_' : '';

        // Test for support.
        if (CSSRule[uPrefix + 'KEYFRAMES_RULE']) {

            // Rule supported; add keyframe rule to test stylesheet.
            style.sheet.insertRule('@'+ hPrefix + 'keyframes ' + rule, 0);

            // Apply animation.
            var animationProp = (hPrefix + 'animation').toCamelCase();
            element.style[animationProp] = 'capTest 1s 0s both';

            // Get initial computed style.
            var before = getComputedStyle(element)[propCamel];

            // Skip to last frame of animation.
            // BUG: Firefox doesn't support reverse or update node style while
            // attached.
            doc.removeChild(element);
            element.style[animationProp] = 'capTest 1s -1s alternate both';
            doc.appendChild(element);
            // BUG: Webkit doesn't update style when animation skipped ahead.
            element.style[animationProp] = 'capTest 1s 0 reverse both';

            // Get final computed style.
            var after = getComputedStyle(element)[propCamel];

            // If before and after are different, property and values are animable.
            canAnimate = before !== after;
            break;
        }
    }

    // Clean up the test elements.
    doc.removeChild(element);
    doc.removeChild(style);

    return canAnimate;
}

// Cribbed from Lea Verou's prefixfree.
String.prototype.toCamelCase = function() {
    return this.replace(/-([a-z])/g, function($0, $1) { return $1.toUpperCase(); })
               .replace('-','');
};

Как использовать

Обязательными аргументами для этого являются свойство для анимации, а также начальные и конечные значения, которые должныбрать.При желании вы можете передать элемент с другим начальным набором стилей, например position: absolute.(Функция клонирует элемент, поэтому вы можете передавать узлы из документа, и они не будут изменены.) Если вы не передадите какой-либо элемент, анимация будет протестирована на div с любыми стилем по умолчанию, которые применяется UA.

Как это работает

Правило анимации ключевых кадров добавляется в фиктивную таблицу стилей, для начального кадра установлено значение from, а для конечного кадра установлено значение to.Эта анимация применяется к элементу.Затем мы проверяем вычисленный стиль для анимированного свойства, чтобы увидеть, не отличается ли он, когда анимация начинается с начального кадра, по сравнению с тем, когда она начинается с последнего кадра.и анимация, и переходы и ключевые кадры одинаковы, и браузер будет применять значения ключевых кадров только в том случае, если свойство поддерживает анимацию.

Предупреждения (прочитайте перед использованием, некоторые из них неприятны!)

Естьнесколько несоответствий в том, как браузеры обрабатывают анимацию.Несколько из них я обошел как можно более перспективным способом;однако некоторые из них являются трудноразрешимыми.

Наиболее примечательно, значения положения анимации Firefox (например, left) на статических элементах, а другие (например, Webkit и Opera) - нет.На самом деле он не перемещает элемент, но значение этого свойства обновляется.Таким образом, вы получите разные результаты в разных браузерах, если попытаетесь анимировать значение позиции, не передавая нестатически позиционированный элемент.

Самые последние версии основных браузеров, поддерживающие переходы CSS, также поддерживают ключевые кадры CSS, хотя некоторыеболее старые версии поддерживают первую, но не последнюю.(Например, Opera 11.)

Наконец, если бы я делал это более элегантно, я бы использовал prefixfree , чтобы определить правильный префикс для непосредственного использования;в настоящее время я проверяю массив префиксов, начиная с версии без префиксов.

3 голосов
/ 13 января 2011

Редактировать: см. Ответ Джордана для хорошей методики обнаружения анимируемых свойств.

Боюсь, что нет простого способа определить, является ли свойствоанимируемый.Тем не менее, свойства по большей части согласованы (единственная проблема, с которой я столкнулся - это переход FF4 + тень текста + преобразование).

http://www.w3.org/TR/css3-transitions/#the-transition-property-property-#properties-from-css-

Firefox 3.6 не поддерживаетcss переходы, вы можете обнаружить это с помощью библиотеки js, такой как Modernizr:

http://www.modernizr.com/

...