CSS3 geçişi bittiğinde geri arama


202

Bir öğeyi (opaklığını 0'a geçirerek) soldurmak ve bittikten sonra DOM'dan öğeyi kaldırmak istiyorum.

Bir animasyon tamamlandıktan sonra "Kaldır" ı belirtebileceğiniz için jQuery'de bu basittir. Ama CSS3 geçişlerini kullanarak animasyon yapmak istersem geçiş / animasyonun ne zaman tamamlandığını bilmek yine de var mı?



Yanıtlar:


334

Geçişler için jQuery aracılığıyla bir geçişin sonunu tespit etmek için aşağıdakileri kullanabilirsiniz:

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

Mozilla mükemmel bir referansa sahiptir:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions#Detecting_the_start_and_completion_of_a_transition

Animasyonlar için çok benzer:

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

Etkinliği tetikleyen tüm tarayıcılarda olay tetiklemeyi desteklemek için tarayıcı ön ekli tüm olay dizelerini aynı anda bind () yöntemine aktarabileceğinizi unutmayın.

Güncelleme:

Duck'ın bıraktığı yorum başına: .one()işleyicinin yalnızca bir kez ateş etmesini sağlamak için jQuery yöntemini kullanırsınız. Örneğin:

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

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

Güncelleme 2:

jQuery bind()yöntemi kullanımdan kaldırılmıştır ve on()yöntem olarak tercih edilmektedir jQuery 1.7.bind()

Ayrıca off(), yalnızca bir kez tetiklenmesini sağlamak için geri arama işlevindeki yöntemi de kullanabilirsiniz . İşte one()yöntemi kullanmaya eşdeğer bir örnek :

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

Referanslar:


13
Ayrıca geri dönen her alt öğe için geri aramanın tetikleneceğini belirtmek gerekir . Geri aramanızın neden beklediğinizden daha fazla tetiklendiğini merak ediyorsanız, bunu akılda tutmak çok önemlidir. Şu an için herhangi bir çözümün farkında değilim.
Lev

22
@Lev, etkinliğin currentTarget'ini hedefiyle karşılaştırarak kolayca hafifletebilirsiniz. Yani şöyle bir şey var: function (event) {if (event.target === event.currentTarget) {/ * Yapılacak şeyler * /}}
Jim Jeffers

5
Evet, yorumu yazdıktan kısa bir süre sonra anladım. > _ <Yine de gönderdiğiniz için teşekkürler; Eminim başkalarına yardım edecek! :)
Lev

9
Biz jQuery v1.7 + api.jquery.com/bind.on() yerine kullanıyoruz.bind()
olo

4
Artık tüm modern tarayıcılar ön düzeltilmemiş etkinliği destekliyor. caniuse.com/#feat=css-transitions Ayrıca "transitionend webkitTransitionEnd" varsa, Chrome'da iki kez tetikleneceğini unutmayın.
Michael S.

17

Başka bir seçenek , CSS3 geçişlerinizi işlemek için jQuery Transit Framework'ü kullanmak olacaktır . Geçişler / efektler mobil cihazlarda iyi performans gösterir ve animasyon efektlerini yapmak için CSS dosyanıza tek bir dağınık CSS3 geçişi satırı eklemenize gerek yoktur.

Bir öğenin üzerine tıkladığınızda opaklığını 0'a geçirecek ve geçiş tamamlandıktan sonra kaldırılacak bir örnek:

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

JS Fiddle Demosu


Geri arama çalışmıyor - belki de transitin API'sındaki bir değişiklik nedeniyle bilmiyorum, ama keman örneği çalışmıyor. Animasyon başlamadan önce gizleme yöntemini tetikler (
kromda denendi

@JonathanLiuti FireFox 25, IE11, Chrome 31 kullanılarak test edilmiştir.
ROFLwTIME

Evet @ROFLwTIME tamamen haklısın - kromun çıldırdığı anlaşılıyor. Kromun temiz bir şekilde yeniden başlatılmasından sonra bugün keman yeniden test edildi ve beklendiği gibi çalışıyor. Benim hatam ! Bunun için üzgünüm.
Jonathan Liuti

14

Gözlenebilecek bir animationendEtkinlik var, buradaki belgelere bakın , ayrıca css transitionanimasyonları için transitionendetkinliği kullanabilirsiniz

Bunların hepsi vanilya JS ile çalışan ek kütüphanelere gerek yoktur

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
Bu, yalnızca bağlantıya yönelik sınırda bir cevaptır . Cevabınızı, burada çok fazla bilgi içerecek şekilde genişletmeli ve bağlantıyı yalnızca referans olması için kullanmalısınız.
Hoşçakal StackExchange

4
JQuery'ye güvenmeyen ilk kişi olduğu için bu oylama. Bir dal için tüm ağacı kesmenin bir anlamı yok.
Aaron Mason

7

Bunun için kullanışlı olabileceği herkes için, burada bir CSS sınıfı aracılığıyla bir CSS animasyonu uygulamak, sonradan geri arama almak için başarıya ulaştığım jQuery bağımlı bir işlev var. Bir Backbone.js App kullanılan beri mükemmel çalışmayabilir, ama belki de yararlı.

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();
}

Ben böyle kullandım

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

Http://mikefowler.me/2013/11/18/page-transitions-in-backbone/ adresinden orijinal fikir

Ve bu kullanışlı görünüyor: http://api.jqueryui.com/addClass/


Güncelleme

Yukarıdaki kod ve diğer seçeneklerle mücadele ettikten sonra, CSS animasyon sonlarını dinlerken çok dikkatli olmanızı öneririm. Birden çok animasyon devam ederken, bu olay dinlemek için çok hızlı bir şekilde dağınık hale gelebilir. Her animasyon için, hatta küçük olanlar için GSAP gibi bir animasyon kütüphanesi öneririm .


Paylaştığınız için teşekkürler, kullandım ve e.stopImmediatePropagation(); self.trigger(this.whichAnimationEvent()); //for purge existing event callback.apply(self);
ekledim

5

Kabul edilen yanıt şu anda Chrome'daki animasyonlar için iki kez tetikleniyor. Muhtemelen bunun da farkında webkitAnimationEndolduğu için animationEnd. Aşağıdakiler kesinlikle sadece bir kez patlar:

/* 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
Animasyon olayları ile uğraştığı için bunun yerine whichAnimationEvent () işlevini çağırmanızı öneririm.
Jakob Løkke Madsen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.