Oddzwonienie po zakończeniu przejścia CSS3

202

Chciałbym wyciszyć element (zmieniając jego krycie na 0), a następnie po zakończeniu usuń element z DOM.

W jQuery jest to proste, ponieważ można określić opcję „Usuń”, która ma się odbywać po zakończeniu animacji. Ale jeśli chcę animować za pomocą przejść CSS3, czy mogę wiedzieć, kiedy przejście / animacja została zakończona?

CJ
źródło
3
powinno być podobne do tego: stackoverflow.com/questions/6186454/…
Nicolas Modrzyk

Odpowiedzi:

334

W przypadku przejść możesz użyć następującego polecenia do wykrycia końca przejścia za pomocą jQuery:

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

Mozilla ma doskonałe referencje:

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

W przypadku animacji jest bardzo podobny:

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

Zauważ, że możesz przekazać wszystkie ciągi zdarzeń poprzedzone przeglądarką do metody bind () jednocześnie, aby obsługiwać uruchamianie zdarzeń we wszystkich przeglądarkach, które je obsługują.

Aktualizacja:

Zgodnie z komentarzem pozostawionym przez Ducka: używasz .one()metody jQuery, aby mieć pewność, że program obsługi odpali tylko raz. Na przykład:

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

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

Aktualizacja 2:

bind()Metoda jQuery jest przestarzała, a on()metoda jest preferowana od dnia jQuery 1.7.bind()

Możesz także użyć off()metody w funkcji wywołania zwrotnego, aby mieć pewność, że zostanie ona uruchomiona tylko raz. Oto przykład równoważny z użyciem one()metody:

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

Bibliografia:

Jim Jeffers
źródło
13
Warto zauważyć, że wywołanie zwrotne zostanie uruchomione dla każdego elementu potomnego, który również jest przesyłany. Należy o tym pamiętać na wypadek, gdybyś zastanawiał się, dlaczego oddzwanianie jest uruchamiane więcej razy, niż się spodziewałeś. Na razie nie jestem świadomy żadnego obejścia.
Lev
22
@ Lew można łatwo to złagodzić, porównując aktualny cel zdarzenia z jego celem. Więc coś w stylu: function (event) {if (event.target === event.currentTarget) {/ * Zrób rzeczy * /}}
Jim Jeffers
5
Tak, zorientowałem się to wkrótce po napisaniu komentarza. > _ <Dziękujemy za opublikowanie; Jestem pewien, że to pomoże innym! :)
Lev
9
Używamy .on()zamiast .bind()jQuery v1.7
olo
4
Wszystkie współczesne przeglądarki obsługują teraz nieokreślone zdarzenie. caniuse.com/#feat=css-transitions Pamiętaj też, że jeśli masz „przejście do webkitTransitionEnd”, zostanie ono uruchomione dwukrotnie w Chrome.
Michael S.
17

Inną opcją byłoby użycie jQuery Transit Framework do obsługi przejść CSS3. Przejścia / efekty działają dobrze na urządzeniach mobilnych i nie musisz dodawać ani jednego wiersza niechlujnych przejść CSS3 w pliku CSS, aby wykonać efekty animacji.

Oto przykład, który zmieni krycie elementu na 0 po kliknięciu i zostanie usunięty po zakończeniu przejścia:

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

JS Fiddle Demo

ROFLwTIME
źródło
Oddzwanianie nie działa - być może jest to spowodowane zmianą interfejsu API tranzytu, nie wiem, ale przykład skrzypiec nie działa.
Uruchamia
@JathanathanLiuti przetestowany przy użyciu FireFox 25, IE11, Chrome 31. Działa dobrze.
ROFLwTIME
Tak, @ROFLwTIME masz całkowitą rację - wygląda na to, że mój chrom oszalał. Ponownie przetestowałem skrzypce po czystym ponownym uruchomieniu Chrome i działa zgodnie z oczekiwaniami. Mój błąd ! Przepraszam za ten.
Jonathan Liuti
14

Jest to animationendwydarzenie, które można zaobserwować w dokumentacji zobaczyć tutaj , również dla CSS transitionanimacji można użyć transitionendzdarzenia

Nie ma potrzeby stosowania dodatkowych bibliotek, które działają z waniliowym 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>

Yehuda Schwartz
źródło
2
Jest to odpowiedź tylko z linkiem granicznym . Powinieneś rozszerzyć swoją odpowiedź, aby zawierała tutaj tyle informacji, i użyj linku tylko w celach informacyjnych.
Do widzenia StackExchange
4
Głosuj na ten, ponieważ jest to pierwszy, który nie polega na jQuery. Nie ma sensu wycinać całego drzewa dla gałęzi.
Aaron Mason
7

Dla każdego, dla kogo może się to przydać, oto funkcja zależna od jQuery, z którą udało mi się zastosować animację CSS za pośrednictwem klasy CSS, a następnie uzyskać oddzwonienie. Może nie działać idealnie, ponieważ miałem go w aplikacji Backbone.js, ale może być użyteczny.

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

Użyłem tego w ten sposób

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

Oryginalny pomysł z http://mikefowler.me/2013/11/18/page-transitions-in-backbone/

I wydaje się to przydatne: http://api.jqueryui.com/addClass/


Aktualizacja

Po zmaganiu się z powyższym kodem i innymi opcjami sugerowałbym bardzo ostrożność przy każdym zakończeniu odsłuchu animacji CSS. Przy wielu animacjach może to bardzo szybko zepsuć się podczas słuchania wydarzeń. Zdecydowanie polecam bibliotekę animacji, taką jak GSAP, dla każdej animacji, nawet tej małej.

David Sinclair
źródło
Dzięki za udostępnienie, korzystałem z niego i edytowałem dodawanie e.stopImmediatePropagation(); self.trigger(this.whichAnimationEvent()); //for purge existing event callback.apply(self);
BomAle
5

Akceptowana odpowiedź jest obecnie uruchamiana dwukrotnie dla animacji w Chrome. Przypuszczalnie dzieje się tak, ponieważ rozpoznaje webkitAnimationEndrównież animationEnd. Następujące elementy z pewnością wystrzelą tylko raz:

/* 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);
        });
Chuck Le Butt
źródło
3
Sugerowałbym zamiast tego wywołać funkcję whichAnimationEvent (), ponieważ dotyczy ona zdarzeń animacyjnych.
Jakob Løkke Madsen