transtionend / animationend事件的特征检测?

时间:2012-10-10 00:04:40

标签: css3 javascript-events css-transitions browser-feature-detection

我正在寻找一种更清晰的方法来检测transitionend的实际名称。我已经看到很多例子只是强力添加处理程序到所有的变化。另外,我不想依赖jQuery(或类似的框架)。

我基本上从这个列表开始,并希望绑定最合适的(即列表中的第一个匹配)。

var transitionendName,
    events = [
        'transitionend',
        'webkitTransitionEnd',
        'MozTransitionEnd',
        'oTransitionEnd'
    ];

// ^^^^^ your code here

myElem.addEventListener(transitionendName, myHandler, false);

有人觉得他们有一个干净的解决方案吗?相同的解决方案可能适用于animationend事件。

编辑: msTransitionEnd和'-ms-'前缀属性were removed in one of the final IE10 release candidates

4 个答案:

答案 0 :(得分:4)

您可以注册所有事件结束名称,然后触发一个非常短的CSS转换,并查看哪一个触发。此外,IE10使用transitionend,因此没有使用msTransitionEnd的浏览器。

以下是如何执行此操作的示例:http://jsfiddle.net/jfriend00/5Zv9m/

var transitionendName,
    events = [
        'transitionend',
        'webkitTransitionEnd',
        'MozTransitionEnd',
        'oTransitionEnd'
    ];

function findTransitionEnd(callback) {
    // add an off-screen element
    var elem = document.createElement("div");
    elem.id = "featureTester";
    document.body.appendChild(elem);

    // clean up temporary element when done
    function cleanup() {
        document.body.removeChild(elem);
        elem = null;
    }

    // set fallback timer in case transition doesn't trigger
    var timer = setTimeout(function() {
        if (!transitionendName) {
            cleanup();
            callback("");
        }
    }, 200);

    // register all transition end names
    for (var i = 0; i < events.length; i++) {
        (function(tname) {
            elem.addEventListener(tname, function() {
                if (!transitionendName) {
                    transitionendName = tname;
                    clearTimeout(timer);
                    cleanup();
                    callback(tname);
                }

            });
        })(events[i]);
    }


    // trigger transition
    setTimeout(function() {
        elem.className = "featureTestTransition";
    }, 1);
}

答案 1 :(得分:4)

另一种符合纯特征检测的变体(而不是纯粹的实用解决方案),但效率更高:

var transitionendNames = [
    'transitionend',
    'webkitTransitionEnd',
    'MozTransitionEnd',
    'oTransitionEnd'
];

/**
 * Helper function to bind to the correct transitionend event
 * @param {function} callback The function to call when the event fires
 */
var transitionend = function(elem, callback) {
    var handler = function(e) {
        //console.log('transitionend == '+e.type);

        // test in case multiple were registered before change
        if (transitionendNames) {
            // store the actual name
            var transitionendName = e.type;

            // every other time, bind only to actual event
            transitionend = function(elem, callback) {
                elem.addEventListener(transitionendName, callback, false);
            };

            // flag for any others
            transitionendNames = null;
        }
        return callback.call(elem, e);
    };

    // until an event has been triggered bind them all
    for (var i=0, len=transitionendNames.length; i<len; i++) {
        elem.addEventListener(transitionendNames[i], handler, false);
    }
};

答案 2 :(得分:3)

我知道这是旧的,但我只想补充一点:style属性并不总是检测animationend / transitionend前缀的好方法。例如,一些Android浏览器不为转换使用前缀,而为JS事件使用webkitAnimationEnd。

答案 3 :(得分:0)

使用@jfriend00的答案/示例,可以更轻松地创建更轻的重量检测。

// cssPrefix is any method which detects the property name
var transition = cssPrefix('transition');

var transitionend = {
    'transition': 'transitionend',
    'webkitTransition': 'webkitTransitionEnd',
    'MozTransition': 'transitionend',
    'OTransition': 'oTransitionEnd'
}[transition];

查看实际操作:http://jsfiddle.net/mckamey/qWPTg/