CSS3 过渡完成时的回调

IT技术 javascript jquery css
2021-02-03 12:50:13

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

在 jQuery 中,这是直截了当的,因为您可以指定在动画完成后发生的“删除”。但是,如果我想使用 CSS3 过渡来制作动画,无论如何要知道过渡/动画何时完成?

6个回答

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

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

Mozilla 有一个很好的参考:

https://developer.mozilla.org/en-US/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:

jQuerybind()方法已被弃用,on()jQuery 1.7.bind()

您还可以off()在回调函数上使用方法来确保它只会被触发一次。这是一个等效于使用one()方法的示例

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

参考:

我们使用.on()而不是.bind()jQuery v1.7 + api.jquery.com/bind
2021-03-11 12:50:13
值得注意的是,每个经过的子元素都会触发回调如果您想知道为什么您的回调被触发的次数比您预期的要多,请记住这一点非常重要。到目前为止,我不知道有任何解决方法。
2021-03-18 12:50:13
是的,我在写评论后不久就明白了。>_< 感谢您发布它;我相信它会帮助别人!:)
2021-03-25 12:50:13
所有现代浏览器现在都支持无前缀事件。 caniuse.com/#feat=css-transitions 另请注意,如果您有“transitionend webkitTransitionEnd”,它将在 Chrome 中触发两次。
2021-03-29 12:50:13
@Lev 您可以通过将事件的 currentTarget 与其目标进行比较来轻松缓解这种情况。所以是这样的: function(event){ if(event.target === event.currentTarget){ /* Do stuff */ } }
2021-04-04 12:50:13

有一个animationend可以观察到事件,请参见此处的文档,对于 csstransition动画,您也可以使用该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>

现在浏览器更加一致——例如,不需要前缀——这个普通的 Javascript 解决方案可能是当今(2020 年)公认的答案。因不依赖 jQuery 来回答一个相对简单的问题而被点赞。
2021-03-17 12:50:13
这是一个边界链接的答案您应该扩展您的答案以在此处包含尽可能多的信息,并且仅将链接用作参考。
2021-03-19 12:50:13
投票给这个,因为它是第一个不依赖于 jQuery 的。为了一根树枝砍掉一整棵树是没有意义的。
2021-03-29 12:50:13

另一种选择是使用jQuery Transit Framework来处理您的 CSS3 转换。过渡/效果在移动设备上表现良好,您不必在 CSS 文件中添加一行凌乱的 CSS3 过渡来制作动画效果。

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

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

JS小提琴演示

@JonathanLiuti 使用 FireFox 25、IE11、Chrome 31 进行了测试。工作正常。
2021-03-17 12:50:13
回调不起作用 - 也许是因为我不知道运输的 api 发生了变化,但小提琴示例不起作用。它在动画运行之前触发 hide 方法(在 chrome 中尝试)
2021-03-28 12:50:13
是的 @ROFLwTIME 你说得对 - 看来我的 chrome 快疯了。今天在彻底重启 chrome 后重新测试了小提琴,它按预期工作。我的错 !对不起这个。
2021-04-08 12:50:13

对于任何人来说,这可能很方便,这里有一个 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);
2021-03-23 12:50:13

接受的答案目前为 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);
        });
我建议改为调用函数 whichAnimationEvent(),因为它处理动画事件。
2021-03-26 12:50:13