6

我正在寻找一种更简洁的方法来检测transitionend. 我已经看到了很多例子,只是蛮力地将处理程序添加到所有变体中。另外,我不想依赖 jQuery(或类似的框架)。

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

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

// ^^^^^ your code here

myElem.addEventListener(transitionendName, myHandler, false);

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

编辑: msTransitionEnd 和 '-ms-' 前缀属性在最终的 IE10 候选版本之一中被删除

4

4 回答 4

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);
}
于 2012-10-10T00:39:59.790 回答
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);
    }
};
于 2012-10-10T16:14:54.913 回答
3

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

于 2014-08-19T13:46:22.563 回答
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/

于 2012-10-10T02:01:47.763 回答