Zdarzenia przejścia CSS3

Odpowiedzi:

210

W3C CSS Transitions Draft

Zakończenie przejścia CSS generuje odpowiednie zdarzenie DOM. Zdarzenie jest uruchamiane dla każdej właściwości, która podlega przejściu. Umożliwia to twórcy treści wykonywanie działań synchronizujących się z zakończeniem przejścia.


Webkit

Aby ustalić, kiedy przejście zostanie zakończone, ustaw funkcję nasłuchiwania zdarzeń JavaScript dla zdarzenia DOM wysyłanego na końcu przejścia. Zdarzenie jest instancją WebKitTransitionEvent, a jego typem jest webkitTransitionEnd.

box.addEventListener( 'webkitTransitionEnd', 
    function( event ) { alert( "Finished transition!" ); }, false );

Mozilla

Istnieje jedno zdarzenie, które jest uruchamiane po zakończeniu przejścia. W Firefoksie zdarzenie jest transitionendw Operze oTransitionEnd, a w WebKit jest webkitTransitionEnd.

Opera

Dostępny jest jeden rodzaj zdarzenia przejścia. oTransitionEndZdarzenie na zakończeniu transformacji.

Internet Explorer

transitionendZdarzenie na zakończeniu transformacji. Jeśli przejście zostanie usunięte przed zakończeniem, zdarzenie nie zostanie uruchomione.


Przepełnienie stosu: jak normalizować funkcje przejścia CSS3 w różnych przeglądarkach?

Davor Lucic
źródło
3
Zwróć uwagę, że wydarzenie nazywa się „przejściem” w Firefoksie i „oTransitionEnd” w Operze
Andreas Köberle
8
Nikt nie wspominał o części pytania dotyczącej przejścia na początek. Czy nie ma możliwości zarejestrowania procedury obsługi zdarzeń, która ma zostać zwolniona przed rozpoczęciem przejścia?
tyler
Czy istnieje teraz standardowy sposób na osiągnięcie tego? Wydaje się, że 2 lata to dużo czasu! Rzeczy prawdopodobnie się zmieniły.
Łagodny Fuzz
@tyler Nie wiem, jak obejść brak przejścia-start.
Davor Lucic
@ Pytanie związane z przepływem stosów powiązane z łagodnym Fuzz ma interesujące rozwiązanie.
Davor Lucic
73

Aktualizacja

Wszystkie współczesne przeglądarki obsługują teraz nieokreślone zdarzenie:

element.addEventListener('transitionend', callback, false);

https://caniuse.com/#feat=css-transitions


Korzystałem z podejścia podanego przez Pete'a, ale teraz zacząłem stosować następujące

$(".myClass").one('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', 
function() {
 //do something
});

Alternatywnie, jeśli używasz bootstrap, możesz po prostu to zrobić

$(".myClass").one($.support.transition.end,
function() {
 //do something
});

Jest tak, ponieważ zawierają one następujące pliki w pliku bootstrap.js

+function ($) {
  'use strict';

  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  // ============================================================

  function transitionEnd() {
    var el = document.createElement('bootstrap')

    var transEndEventNames = {
      'WebkitTransition' : 'webkitTransitionEnd',
      'MozTransition'    : 'transitionend',
      'OTransition'      : 'oTransitionEnd otransitionend',
      'transition'       : 'transitionend'
    }

    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return { end: transEndEventNames[name] }
      }
    }

    return false // explicit for ie8 (  ._.)
  }


  $(function () {
    $.support.transition = transitionEnd()
  })

}(jQuery);

Należy pamiętać, że zawierają one także funkcję emulateTransitionEnd, która może być potrzebna do zapewnienia, że ​​zawsze nastąpi wywołanie zwrotne.

  // http://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false, $el = this
    $(this).one($.support.transition.end, function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    setTimeout(callback, duration)
    return this
  }

Należy pamiętać, że czasami to zdarzenie nie jest uruchamiane, zwykle w przypadku, gdy właściwości się nie zmieniają lub farba nie jest wyzwalana. Aby mieć pewność, że zawsze otrzymamy oddzwonienie, ustawmy limit czasu, który wyzwoli zdarzenie ręcznie.

http://blog.alexmaccaw.com/css-transitions

Tomek
źródło
3
Nie możesz zrobić czegoś takiego. W niektórych przypadkach callbaack zostanie uruchomiony więcej niż jeden raz.
sebastian
11
W przeglądarkach, które przechowują zarówno prefiksy, jak i zwykłe nazwy zdarzeń. Można to obejść, używając .one zamiast
.on
61

Wszystkie współczesne przeglądarki obsługują teraz nieokreślone zdarzenie:

element.addEventListener('transitionend', callback, false);

Działa w najnowszych wersjach Chrome, Firefox i Safari. Nawet IE10 +.

neave
źródło
16

W Operze 12, gdy łączysz się za pomocą zwykłego JavaScript, „oTransitionEnd” będzie działać:

document.addEventListener("oTransitionEnd", function(){
    alert("Transition Ended");
});

jednak jeśli łączysz się przez jQuery, musisz użyć „otransitionend”

$(document).bind("otransitionend", function(){
    alert("Transition Ended");
});

Jeśli korzystasz z Modernizr lub bootstrap-przejście.js, możesz po prostu dokonać zmiany:

var transEndEventNames = {
    'WebkitTransition' : 'webkitTransitionEnd',
    'MozTransition'    : 'transitionend',
    'OTransition'      : 'oTransitionEnd otransitionend',
    'msTransition'     : 'MSTransitionEnd',
    'transition'       : 'transitionend'
},
transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];

Można znaleźć tutaj również informacje http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/

Piotr
źródło
6

Tylko dla zabawy, nie rób tego!

$.fn.transitiondone = function () {
  return this.each(function () {
    var $this = $(this);
    setTimeout(function () {
      $this.trigger('transitiondone');
    }, (parseFloat($this.css('transitionDelay')) + parseFloat($this.css('transitionDuration'))) * 1000);
  });
};


$('div').on('mousedown', function (e) {
  $(this).addClass('bounce').transitiondone();
});

$('div').on('transitiondone', function () {
  $(this).removeClass('bounce');
});
yckart
źródło
3

Jeśli chcesz po prostu wykryć tylko jeden koniec przejścia, bez korzystania ze struktury JS, oto mała wygodna funkcja narzędziowa:

function once = function(object,event,callback){
    var handle={};

    var eventNames=event.split(" ");

    var cbWrapper=function(){
        eventNames.forEach(function(e){
            object.removeEventListener(e,cbWrapper, false );
        });
        callback.apply(this,arguments);
    };

    eventNames.forEach(function(e){
        object.addEventListener(e,cbWrapper,false);
    });

    handle.cancel=function(){
        eventNames.forEach(function(e){
            object.removeEventListener(e,cbWrapper, false );
        });
    };

    return handle;
};

Stosowanie:

var handler = once(document.querySelector('#myElement'), 'transitionend', function(){
   //do something
});

to jeśli chcesz anulować w pewnym momencie, nadal możesz to zrobić

handler.cancel();

Jest również dobry do innych zastosowań związanych z wydarzeniami :)

OpherV
źródło