2013-12-10 21 views
17

In meiner Close-Funktion möchte ich alle meine DOM-Bereinigung tun, nachdem die CSS-Übergänge beendet sind. Es kann jedoch sein, dass keine Übergänge mehr laufen - möglicherweise mehrstufige - (die Pflege der Stylesheets liegt nicht in meinen Händen).Kann ich feststellen, ob ein beliebiger CSS-Übergang gestartet wurde?

Wie würde ich mich über eine Funktion, so etwas wie die folgenden

function close() { 
    myEl.removeClass('open'); 
    if (animation is running/about to be run) { 
    // wait for transition to end, then recursively check to see if another 
    // one has started, wait for that ... 
    // then 
    cleanUpDOM(); 
    } else { 
    cleanUpDOM(); 
    } 
} 

Meine Gedanken sind so weit das Schreiben der Anfangsüberprüfung in einem Timeout/request, um wickeln die Animation eine Chance zu beginnen dann zu geben Überprüfung um zu sehen, ob es läuft. Leider habe ich ohne ein transitionstart Ereignis keine Ahnung, wie man überprüft, ob ein Übergang begonnen hat.

bearbeiten Antworten jquery empfehlen sind irrelevant, da jquery Animationen Javascript Animationen sind, nicht CSS-Übergänge

+0

wenn Sie wissen, welche Eigenschaft animiert wird, kann man bestimmen, ob die Animation läuft durch die Elemente aktuellen Eigenschaftswert zu vergleichen mit dem, was es Wert CSS-Stil (auch bekannt als Ziel) ist? – milks

+0

@milks Im Allgemeinen werde ich nicht wissen, was umgestellt wird, oder sogar, wenn irgendetwas überhaupt umgestellt wird. (Worst-Case-Szenario ist sogar noch schwieriger - ich weiß vielleicht nicht einmal, ob der Übergang auf dem äußeren Element ist, zB im Overlay kann der innere Inhaltsbereich auf einen Punkt schrumpfen, obwohl das äußere Overlay nur schwarz bleibt ... aber dieses Szenario ist nicht 't so wichtig für jetzt) ​​ – wheresrhys

+0

Ich denke, das ist ein Duplikat von http://stackoverflow.com/questions/2087510/callback-on-css-transition –

Antwort

1

Über transitionStart und transitionEnd Ereignisse:

Der Übergang kann nicht beginnt, aus dem Nichts. Normalerweise beginnt der Übergang nach einem Ereignis, bei dem Sie den Status des DOM-Elements ändern, indem Sie Stile nach Klasse oder etwas anderem ändern. So Sie wissen, wann der Übergang beginnt, weil Sie es in Ihrem Code starten.

Während der Übergang Benutzer I/O nicht blockiert, so ist der Übergang asynchron und dann Übergang wird Sie wissen nicht richtig beenden. Sie brauchen also transitionEnd Ereignis, um etwas zu tun, dann ist der Übergang in Javascript abgeschlossen.

Über transitionEnd Veranstaltung: Sehen Sie nur die jsfiddle

+4

Ich starte es nicht explizit in meinem 'js' Code. Ich füge eine Klasse in 'js' hinzu, die einige Stile in der' css' anwendet, die * einen * Übergang * beinhalten kann, so dass 'js' nicht weiß, ob eine Transition beginnt – wheresrhys

+0

Sie können die Übergangsunterstützung (mit Präfixen oder nicht) überprüfen) von [Modernisr] (http://modernizr.com/). Wenn der Übergang unterstützt wird, können Sie das style-Objekt nach "transitionDelay", "transitionDuration" und "transitionProperty" überprüfen und die Werte erhalten, die wissen, ob der Übergang beginnt oder nicht. – Pinal

+0

Sie können nicht sicher wissen, wann der Übergang gestartet wird, da es sich um eine asynchrone Operation handelt, die der Browser ausführt, wenn Sie nicht wissen, wann. Werfen Sie einen Blick auf: https://stackoverflow.com/questions/27275872/race-condition-with-css-transitions-and-transitionend-event-cannot-find-a-solu – demian85

1

Hier ist meine Lösung so weit - ein bisschen hacky und funktioniert nur, wenn welches Element Übergang könnte bekannt ist, und arbeitet nicht mit transition-property: all ... aber es ist ein vielversprechender Start

function toCamelStyleProp (str) { 
    return str.replace(/(?:\-)([a-z])/gi, function ($0, $1) { 
     return $1.toUpperCase(); 
    }); 
} 

function toHyphenatedStyleProp (str) { 
    return str.replace(/([A-Z])/g, function (str,m1) { 
     return '-' + m1.toLowerCase(); 
    }).replace(/^ms-/,'-ms-'); 
} 

function getPrefixedStyleProp (prop) { 
    prop = toCamelStyleProp(prop); 
    prop = Modernizr.prefixed(prop); 
    return toHyphenatedStyleProp(prop); 
} 

function getStyleProperty (el, prop) { 
    return getComputedStyle(el,null).getPropertyValue(getPrefixedStyleProp(prop)); 
} 

function doAfterTransition ($wrapper, cssClass, mode, $transitioningEl, callback) { 
    $transitioningEl = $transitioningEl || $wrapper; 

    var transitioningEl = $transitioningEl[0], 
     duration = +getStyleProperty(transitioningEl, 'transition-duration').replace(/[^\.\d]/g, ''), 
     transitioners = getStyleProperty(transitioningEl, 'transition-property').split(' '), 
     initialState = [], 
     changedState = [], 
     i, 
     callbackHasRun = false, 

     //makes sure callback doesn't get called twice by accident 
     singletonCallback = function() { 
      if (!callbackHasRun) { 
       callbackHasRun = true; 
       callback(); 
      } 
     }; 

    // if no transition defined just call the callback 
    if (duration === 0) { 
     $wrapper[mode + 'Class'](cssClass); 
     callback(); 
     return; 
    } 

    for (i = transitioners.length - 1;i>=0;i--) { 
     initialState.unshift(getStyleProperty(transitioningEl, transitioners[i])); 
    } 

    $wrapper[mode + 'Class'](cssClass); 

    setTimeout(function() { 
     for (i = transitioners.length - 1;i>=0;i--) { 
      changedState.unshift(getStyleProperty(transitioningEl, transitioners[i])); 
     } 

     for (i = transitioners.length - 1;i>=0;i--) { 
      if (changedState[i] !== initialState[i]) { 
       $transitioningEl.transitionEnd(singletonCallback); 

       // failsafe in case the transitionEnd event doesn't fire 
       setTimeout(singletonCallback, duration * 1000); 
       return; 
      } 
     } 
     singletonCallback(); 
    }, 20); 
} 
-1

Wenn Sie CSS-Übergang zu machen Planung sind, können Sie jQuery Plugin Transit Besuche http://ricostacruz.com/jquery.transit/

Sehr stark und nützlich, können Sie mit x Wert umwandeln. css ('x') zum Beispiel.

-1

Auf animation.css fand ich dies.

Sie können auch erkennen, wenn eine Animation endet:

$('#yourElement').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', doSomething); 

read full doc here

1

Es gibt keine Art und Weise ist (die ich kenne) zu erkennen, ob ein Übergang zur Zeit im Hintergrund arbeiten, ohne das Element zu wissen das wird umgestellt.

Wenn Sie jedoch vom Übergang zu Keyframeanimationen wechseln können, müssen Sie das so benötigte Event - AnimationStart und AnimationEnd haben und dann wird es einfach herauszufinden, ob Animationen laufen.

1

Haben Sie den JQuery-Pseudo ": animiert" ausprobiert?

if ($ (Elem) .ist (': animated')) {...}

Weiterehttp://api.jquery.com/animated-selector/

+1

Das funktioniert nur mit jquery Javascript-Animation https: //github.com/jquery/jquery/blob/master/src/effects/animatedSelector.js - sehen Sie, wie es erwartet, dass es in jquery einen Timer gibt – wheresrhys

-1

Sie könnten JQuery verwenden, die zum Beispiel viel einfacher wäre, Sie könnten eine Callback-Funktion

0
verwenden .animate wie diese

(function(){ 
      var box = $('div.box') 
      $('button').on('click', function(){ 
       box.animate({ 'font-size' : '40px'}) 
       .animate({'color': 'red'}); 
      }) 
     })(); 

oder einfach tun

Hier ist eine Funktion, die darauf wartet, dass die Seite HTML stabil wird. wenn alle Animationen beendet sind. Im folgenden Beispiel wird darauf gewartet, dass der HTML-Code für 200 Millisekunden unverändert bleibt und eine maximale Zeitüberschreitung von 2 Sekunden besteht.

Rufen Sie die Funktion mit ...

waitUntilHtmlStable(yourCallback, 200, 2000); 

Die Funktion ...

waitUntilHtmlStable = function (callback, unchangedDuration, timeout, unchangedElapsed, html) { 
    var sleep = 50; 
    window.setTimeout(function() { 
     var newHtml = document.documentElement.innerHTML; 
     if (html != newHtml) unchangedElapsed = 0; 
     if (unchangedElapsed < unchangedDuration && timeout > 0) 
      waitUntilHtmlStable(callback, unchangedDuration, timeout - interval, unchangedElapsed + interval, newHtml); 
     else 
      callback(); 
    }, sleep); 
}; 

In meinem Fall wollte ich sicher, dass neue Elemente vorhanden sein, wo. Wenn Sie Animation wollen Bewegung verfolgen dann die document.documentElement.innerHTML ändern

JSON.stringify(Array.prototype.slice.call(document.documentElement.getElementsByTagName("*"), 0) 
.map(function(e) { 
     var x = e; 
     var r = x.getBoundingClientRect(); 
     while (r.width == 0 || r.height == 0) { 
      x = x.parentNode; 
      r = x.getBoundingClientRect(); 
     } 
     return r; 
    })); 
Verwandte Themen