CSS3过渡完成时回调


202

我想淡出一个元素(将其不透明度转换为0),然后在完成后从DOM中删除该元素。

在jQuery中,这很简单,因为您可以指定动画完成后进行的“删除”操作。但是,如果我希望使用CSS3过渡进行动画处理,是否可以知道过渡/动画何时完成?



Answers:


334

对于过渡,您可以使用以下内容通过jQuery检测过渡的结束:

$("#someSelector").bind("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){ ... });

Mozilla具有出色的参考:

https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#Detecting_the_start_and_completion_of_a_transition

对于动画,它非常相似:

$("#someSelector").bind("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", function(){ ... });

请注意,您可以将所有浏览器前缀的事件字符串同时传递到bind()方法中,以在所有支持该事件的浏览器上支持事件触发。

更新:

根据Duck留下的评论:您使用jQuery的.one()方法来确保处理程序仅触发一次。例如:

$("#someSelector").one("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){ ... });

$("#someSelector").one("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd", function(){ ... });

更新2:

jQuery bind()方法已被弃用,从开始,on()最好使用method方法jQuery 1.7bind()

您还可以off()在回调函数上使用method,以确保仅将其触发一次。这是一个等效于using one()方法的示例:

$("#someSelector")
.on("animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd",
 function(e){
    // do something here
    $(this).off(e);
 });

参考文献:


13
值得注意的是,也会为每个传递的子元素触发回调。要牢记这一点非常重要,以防万一您想知道为什么您的回调被触发的次数比您预期的要多。截至目前,我还没有任何解决方法。
Lev

22
@Lev,您可以通过将事件的currentTarget与目标进行比较来轻松缓解这种情况。就像这样:function(event){if(event.target === event.currentTarget){/ *做东西* /}}
Jim Jeffers 2013年

5
是的,我在写评论后不久就发现了这一点。> _ <感谢您发布它;我相信它会帮助别人!:)
Lev

9
我们用.on(),而不是.bind()jQuery的V1.7 + api.jquery.com/bind
OLO

4
现在,所有现代浏览器都支持unprefixed事件。 caniuse.com/#feat=css-transitions 另请注意,如果您具有“ transitionend webkitTransitionEnd”,则它将在Chrome中触发两次。
Michael S.

17

另一个选择是使用jQuery Transit Framework处理CSS3过渡。过渡/效果在移动设备上的效果很好,您不必在CSS文件中添加一行凌乱的CSS3过渡即可制作动画效果。

这是一个示例,当您单击元素时,它将元素的不透明度转换为0,并在转换完成后将其移除:

$("#element").click( function () {
    $('#element').transition({ opacity: 0 }, function () { $(this).remove(); });
});

JS小提琴演示


回调无法正常工作-可能是由于我不知道公交API的更改所致,但是小提琴示例无法正常工作。它会在动画运行之前触发hide方法(在chrome中尝试)
Jonathan Liuti 2013年

@JonathanLiuti已使用FireFox 25,IE11,Chrome 31测试。
ROFLwTIME

是的@ROFLwTIME您完全正确-看来我的Chrome快疯了。在完全重新启动chrome后,今天重新测试了小提琴,它的工作正常。我的错 !对不起,这回合。
乔纳森·刘蒂

14

有一个animationend可以观察到的事件,请参见此处的文档,对于css transition动画,您也可以使用该transitionend事件

不需要额外的库,这些库都可以与Vanilla JS一起使用

document.getElementById("myDIV").addEventListener("transitionend", myEndFunction);
function myEndFunction() {
	this.innerHTML = "transition event ended";
}
#myDIV {transition: top 2s; position: relative; top: 0;}
div {background: #ede;cursor: pointer;padding: 20px;}
<div id="myDIV" onclick="this.style.top = '55px';">Click me to start animation.</div>


2
这是边界链接的答案。您应该扩展答案以在此处包含尽可能多的信息,并且仅将链接用作参考。
再见StackExchange,

4
投票支持它,因为它是不依赖jQuery的第一个。砍掉整棵树作为分支没有意义。
亚伦·梅森

7

对于可能对此有用的任何人,这是一个与jQuery相关的函数,我成功通过CSS类应用CSS动画,然后从其后获取回调。自从我在Backbone.js应用程序中使用它以来,它可能无法完美运行,但可能很有用。

var cssAnimate = function(cssClass, callback) {
    var self = this;

    // Checks if correct animation has ended
    var setAnimationListener = function() {
        self.one(
            "webkitAnimationEnd oanimationend msAnimationEnd animationend",
            function(e) {
                if(
                    e.originalEvent.animationName == cssClass &&
                    e.target === e.currentTarget
                ) {
                    callback();
                } else {
                    setAnimationListener();
                }
            }
        );
    }

    self.addClass(cssClass);
    setAnimationListener();
}

我有点像这样

cssAnimate.call($("#something"), "fadeIn", function() {
    console.log("Animation is complete");
    // Remove animation class name?
});

最初的想法来自http://mikefowler.me/2013/11/18/page-transitions-in-backbone/

这似乎很方便:http : //api.jqueryui.com/addClass/


更新资料

在尝试了上面的代码和其他选项之后,我建议在收听CSS动画结束时要非常谨慎。随着多个动画的进行,事件侦听会很快变得混乱。我强烈建议为每个动画,甚至是小的动画,都提供一个像GSAP这样的动画库。


感谢分享,我使用了它并进行了编辑添加 e.stopImmediatePropagation(); self.trigger(this.whichAnimationEvent()); //for purge existing event callback.apply(self);
-BomAle

5

目前,对于Chrome中的动画,已接受的答案会触发两次。大概是因为它识别webkitAnimationEndanimationEnd。以下内容肯定只会触发一次:

/* From Modernizr */
function whichTransitionEvent(){

    var el = document.createElement('fakeelement');
    var transitions = {
        'animation':'animationend',
        'OAnimation':'oAnimationEnd',
        'MSAnimation':'MSAnimationEnd',
        'WebkitAnimation':'webkitAnimationEnd'
    };

    for(var t in transitions){
        if( transitions.hasOwnProperty(t) && el.style[t] !== undefined ){
            return transitions[t];
        }
    }
}

$("#elementToListenTo")
    .on(whichTransitionEvent(),
        function(e){
            console.log('Transition complete!  This is the callback!');
            $(this).off(e);
        });

3
我建议改为调用函数whichAnimationEvent(),因为它处理动画事件。
JakobLøkkeMadsen
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.