web-dev-qa-db-fra.com

Les transitions CSS ne fonctionnent pas lorsqu'elles sont attribuées via JavaScript

J'ai de gros problèmes en essayant d'appliquer des transitions CSS3 à un diaporama via JavaScript.

Fondamentalement, le JavaScript récupère toutes les diapositives du diaporama et applique les classes CSS aux éléments appropriés pour donner un effet animé Nice. S'il n'y a pas de support pour les transitions CSS3, il appliquera simplement les styles sans transition.

Maintenant, mon "petit" problème. Tout fonctionne comme prévu, toutes les diapositives obtiennent les styles corrects, le code s'exécute sans bogues (jusqu'à présent). Mais les transitions spécifiées ne fonctionnent pas, même si les styles appropriés ont été appliqués. De plus, les styles et les transitions fonctionnent lorsque je les applique moi-même par l'intermédiaire de l'inspecteur.

Comme je ne pouvais pas trouver d'explication logique moi-même, j'ai pensé que quelqu'un ici pourrait y répondre, joli s'il vous plaît?

J'ai rassemblé un petit exemple du code actuel: http://g2f.nl/38rvma Ou utilisez JSfiddle (pas d'images): http://jsfiddle.net/5RgGV/1/

26
Jon Koops

Pour que transition fonctionne, il faut que trois choses se passent.

  1. l'élément doit avoir la propriété explicitement définie, dans ce cas: opacity: 0;
  2. la transition doit être définie pour l'élément: transition: opacity 2s;
  3. la nouvelle propriété doit être définie: opacity: 1

Si vous attribuez dynamiquement 1 et 2, comme vous le faites dans votre exemple, il faut un délai avant 3 pour que le navigateur puisse traiter la demande. Cela fonctionne lorsque vous déboguez, c'est que vous créez ce retard en le parcourant pas à pas, ce qui donne du temps au navigateur pour le traiter. Donnez un délai à l'attribution de .target-fadein:

window.setTimeout( function() { slides[targetIndex].className += " target-fadein"; }, 100 ); 

Ou mettez directement .target-fadein-begin dans votre code HTML afin qu’il soit analysé au chargement et qu’il soit prêt pour la transition.

L'ajout de transition à un élément n'est pas ce qui déclenche l'animation, la modification de la propriété s'effectue.

Démo: http://jsfiddle.net/ThinkingStiff/QNnnQ/

HTML:

<div id="fade1" class="fadeable">fade 1 - works</div>
<div id="fade2">fade 2 - doesn't work</div>
<div id="fade3">fade 3 - works</div>

CSS:

.fadeable {
    opacity: 0;
}

.fade-in {
    opacity: 1;
    transition:             opacity 2s;
        -moz-transition:    opacity 2s;
        -ms-transition:     opacity 2s;
        -o-transition:      opacity 2s;
        -webkit-transition: opacity 2s;
}

Scénario:

//works
document.getElementById( 'fade1' ).className += ' fade-in';

//doesn't work
document.getElementById( 'fade2' ).className = 'fadeable';
document.getElementById( 'fade2' ).className += ' fade-in';

//works
document.getElementById( 'fade3' ).className = 'fadeable';
window.setTimeout( function() {

    document.getElementById( 'fade3' ).className += ' fade-in';

}, 100);
48
ThinkingStiff

Trick le moteur de mise en page!

function finalizeAndCleanUp (event) {
    if (event.propertyName == 'opacity') {
        this.style.opacity = '0'
        this.removeEventListener('transitionend', finalizeAndCleanUp)
    }
}
element.style.transition = 'opacity 1s'
element.style.opacity = '0'
element.addEventListener('transitionend', finalizeAndCleanUp)
// next line's important but there's no need to store the value
element.offsetHeight
element.style.opacity = '1'

Comme déjà mentionné, transitions fonctionne en interpolant de l'état A à l'état B. Si votre script apporte des modifications à la même fonction, le moteur de présentation ne peut pas séparer où l'état A se termine et B commence. Sauf si vous lui donnez un indice.

Comme il n'y a pas de moyen officiel pour faire cette suggestion, vous devez vous fier aux effets secondaires de certaines fonctions. Dans ce cas, .offsetHeight getter qui oblige implicitement le moteur de présentation à s'arrêter, à évaluer et à calculer toutes les propriétés définies et à renvoyer une valeur. Cela devrait généralement être évité pour des raisons de performances, mais dans notre cas, c’est exactement ce dont nous avons besoin: la consolidation d’états.

Code de nettoyage ajouté pour être complet.

4
transistor09

Certaines personnes ont demandé pourquoi il y avait un retard. La norme veut permettre à plusieurs transitions, appelées événements de changement de style, de se produire en même temps (par exemple, un élément qui s'estompe en même temps qu'il passe en mode d'affichage). Malheureusement, il ne définit pas de manière explicite de regrouper les transitions que vous souhaitez effectuer en même temps. Au lieu de cela, il permet aux navigateurs de choisir arbitrairement les transitions qui se produisent au même moment, en fonction de la distance qui les sépare. La plupart des navigateurs semblent utiliser leur fréquence d'actualisation pour définir cette heure.

Voici la norme si vous voulez plus de détails: http://dev.w3.org/csswg/css-transitions/#starting

1
user3723889