CSS3-Übergangsereignisse

190

Gibt es Ereignisse, die von einem Element ausgelöst werden, um zu überprüfen, ob ein CSS3-Übergang begonnen oder beendet wurde?

Andreas Köberle
quelle

Antworten:

210

W3C CSS Transitions Draft

Der Abschluss eines CSS-Übergangs generiert ein entsprechendes DOM-Ereignis. Für jede Eigenschaft, die einen Übergang durchläuft, wird ein Ereignis ausgelöst. Auf diese Weise kann ein Inhaltsentwickler Aktionen ausführen, die mit dem Abschluss eines Übergangs synchronisiert werden.


Webkit

Um festzustellen, wann ein Übergang abgeschlossen ist, legen Sie eine JavaScript-Ereignis-Listener-Funktion für das DOM-Ereignis fest, das am Ende eines Übergangs gesendet wird. Das Ereignis ist eine Instanz von WebKitTransitionEvent und hat den Typ webkitTransitionEnd.

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

Mozilla

Es gibt ein einzelnes Ereignis, das ausgelöst wird, wenn Übergänge abgeschlossen sind. In Firefox ist das Ereignis transitionend, in Opera oTransitionEndund in WebKit webkitTransitionEnd.

Oper

Es ist eine Art von Übergangsereignis verfügbar. Das oTransitionEndEreignis tritt nach Abschluss des Übergangs auf.

Internet Explorer

Das transitionendEreignis tritt nach Abschluss des Übergangs auf. Wenn der Übergang vor Abschluss entfernt wird, wird das Ereignis nicht ausgelöst.


Stapelüberlauf: Wie normalisiere ich CSS3-Übergangsfunktionen über Browser hinweg?

Davor Lucic
quelle
3
Beachten Sie, dass das Ereignis in Firefox "Transitionend" und in Opera
Andreas Köberle
8
Niemand hat etwas über den Übergang-Start-Teil der Frage erwähnt. Gibt es keine Möglichkeit, einen Ereignishandler zu registrieren, der vor Beginn des Übergangs ausgelöst werden soll?
Tyler
Gibt es jetzt einen Standardweg, um dies zu erreichen? 2 Jahre scheinen eine lange Zeit zu sein! Die Dinge haben sich wahrscheinlich geändert.
Mild Fuzz
@tyler Ich weiß nicht, wie ich den Mangel an Übergängen umgehen soll.
Davor Lucic
@Mild Fuzz verknüpfte Stackoverflow-Frage hat interessante Lösung.
Davor Lucic
73

Aktualisieren

Alle modernen Browser unterstützen jetzt das nicht festgelegte Ereignis:

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

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


Ich habe den Ansatz von Pete verwendet, aber jetzt habe ich angefangen, Folgendes zu verwenden

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

Wenn Sie Bootstrap verwenden, können Sie dies auch einfach tun

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

Dies liegt daran, dass sie Folgendes in bootstrap.js enthalten

+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);

Beachten Sie, dass sie auch eine emulateTransitionEnd-Funktion enthalten, die möglicherweise erforderlich ist, um sicherzustellen, dass immer ein Rückruf erfolgt.

  // 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
  }

Beachten Sie, dass dieses Ereignis manchmal nicht ausgelöst wird, normalerweise, wenn sich die Eigenschaften nicht ändern oder keine Farbe ausgelöst wird. Um sicherzustellen, dass wir immer einen Rückruf erhalten, legen wir eine Zeitüberschreitung fest, die das Ereignis manuell auslöst.

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

Tom
quelle
3
So etwas kann man nicht machen. In einigen Fällen wird Callbaack mehrmals ausgelöst.
Sebastian
11
In Browsern, in denen sowohl die vorangestellten als auch die regulären Ereignisnamen beibehalten werden. Sie können es umgehen, indem Sie .one anstelle von .on
AlexG
61

Alle modernen Browser unterstützen jetzt das nicht festgelegte Ereignis:

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

Funktioniert in den neuesten Versionen von Chrome, Firefox und Safari. Sogar IE10 +.

Neave
quelle
16

In Opera 12 funktioniert 'oTransitionEnd', wenn Sie mit einfachem JavaScript binden:

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

Wenn Sie jedoch über jQuery binden, müssen Sie 'otransitionend' verwenden.

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

Wenn Sie Modernizr oder bootstrap-Transition.js verwenden, können Sie einfach eine Änderung vornehmen:

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

Hier finden Sie auch einige Informationen http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/

Peter
quelle
6

Nur zum Spaß, tu das nicht!

$.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
quelle
3

Wenn Sie nur ein einziges Übergangsende erkennen möchten, ohne ein JS-Framework zu verwenden, finden Sie hier eine praktische Dienstprogrammfunktion:

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

Verwendung:

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

Wenn Sie dann irgendwann abbrechen möchten, können Sie dies trotzdem tun

handler.cancel();

Es ist auch gut für andere Event-Verwendungen :)

OpherV
quelle