Chaîne jQuery addClass pour effectuer des transitions CSS

Ce que j’aimerais faire ( fauché ):

 $('button').click(function () { $('div').css({ 'transition': 'left 1000ms' }).addClass('left').addClass('left_more'); }); 

http://jsfiddle.net/0bm4wq7h/13/

Toujours cassé :

 
 $('button').click(function () { $('div').css({ 'transition': 'left 1000ms' }).addClass('left'); console.log('test'); $('div').addClass('left_more'); }); 

http://jsfiddle.net/fwL3dwz2/3/

Mais cela fonctionne :

 
 $('button').click(function () { $('div').css({ 'transition': 'left 1000ms' }).addClass('left'); console.log($('div').css('left')); $('div').addClass('left_more'); }); 

http://jsfiddle.net/j8x0dzbz/5/

Je sais que j’ai besoin d’un sharepoint départ pour ma transition CSS. C’est pourquoi j’ai ajouté la classe de left .

Pourquoi jQuery ne fait-il pas la transition avant mon # 3?

Mettre à jour:

J’avais donc accepté la réponse de Stryner, parce que cela fonctionnait pour moi et maintenant, j’ai le même problème. Le code ci-dessus était une version simplifiée de ce JavaScript:

 $('#screen_wrapper img:eq(0)').removeClass().addClass('prep'); //starting point window.getComputedStyle(document.getElementById('photo'+0)).left; //force the the styling to get recomputated using raw JavaScript $('#screen_wrapper img:eq(0)').css('left');//force the the styling to get recomputated using jQuery $('#screen_wrapper img:eq(0)').addClass('animate_in');//animate to the "animate_in" class coordinates from the "prep" class coordinates 

Ce qui se passe, c’est que je reçois l’animation à partir des coordonnées avant le cours de prep .

Voici le cours de prep :

 #screen_wrapper img.prep { top: 0px; left: 506px; } 

Mais l’image commence réellement à partir de cette classe qui est supprimée à l’aide de la méthode jQuery de removeClass() :

 .animate_out { visibility: visible; top: 0px; left: -506px; } 

La propriété de transition fonctionne correctement:

 $('#screen_wrapper img').css('transition','left 1000ms'); 

Je doute que ces forcer recalculer le style:

 window.getComputedStyle(document.getElementById('photo'+0)).left; $('#screen_wrapper img:eq(0)').css('left'); 

J’utilise du chrome:

 Version 45.0.2454.101 Ubuntu 14.04 (64-bit) 

Mettre à jour

Exemple de cela ne fonctionne pas: http://jsfiddle.net/me8ukkLe/12/

Votre transition fonctionne dans le troisième cas lorsqu’elle appelle $('div').css('left') car jQuery appellera la méthode window.getComputedStyle (ou une méthode très similaire en fonction des problèmes de compatibilité de navigateur). Dans un article de blog de Tim Taubert (un employé de Mozilla), l’astuce est décrite:

getComputedStyle() associé à l’access à une valeur de propriété, efface toutes les modifications de style en attente et oblige le moteur de présentation à calculer l’état actuel de notre

.

Sans forcer ce recalcul de mise en page, le recalcul est retardé jusqu’à l’ajout des deux classes ( left et left-more ), ce qui calculera sa position à 400px .

Exemple Fiddle – Utiliser getComputedStyle et accéder à getComputedStyle

“Les transitions CSS3 vous permettent de modifier les valeurs de propriété en douceur (d’une valeur à l’autre), sur une durée donnée.”

1er scénario posté:

Pour que la transition css fonctionne, vous devez spécifier la propriété css de l’élément sur lequel vous souhaitez effectuer la transition. Dans votre exemple, vous effectuez une transition sur la propriété left mais sa valeur initiale n’est pas définie dans le div css .

Afin de résoudre ce problème, il suffit d’append la propriété left .

 div { position: absolute; width: 10px; height: 10px; background-color: red; left: 0px; } 

Exemple de travail: http://jsfiddle.net/0bm4wq7h/14/

2ème scénario posté vs 3ème scénario posté:

Bien que la propriété définie pour la div ne soit pas définie dans les deux exemples, le troisième scénario fonctionne par rapport au deuxième scénario en raison du retard causé par console.log .

Dans la première déclaration,

 $('div').css({ 'transition': 'left 1000ms' }).addClass('left'); 

class left est ajoutée à l’élément div , ce qui ajoute en interne la propriété left . Mais append le fichier console.log ($ (‘div’). Css (‘left’) appelle window.getComputedStyle (comme mentionné par Stryner) qui enregistre la valeur calculée et ajoute $('div').addClass('left_more'); fondamentalement, cela lui donne l’opportunité d’effectuer la transition de left : 100px à left : 600px left : 100px .

Bonne question! Ce comportement semble définitivement étrange au début. C’est aussi un peu délicat d’expliquer cela clairement, mais pour commencer, comprenez ce qui suit:

1) Les fonctions Javascript s’exécutent de manière atomique

Dans JS, les fonctions sont toujours exécutées du début à la fin, sans aucune autre opération possible à mi-parcours. Cela revient à dire que JS est un langage à un seul thread .

2) Le navigateur ne peut pas interrompre javascript non plus

Non seulement le code JS est empêché de s’exécuter au milieu d’une fonction, mais l’onglet du navigateur dans lequel le code est exécuté ne sera pas non plus interjecté! Cela signifie que (presque) TOUT sur une page Web est interrompu (repeints, animations, application de feuille de style, etc.) lorsqu’une fonction JS est en cours d’exécution. Si vous voulez tester cela, vous pouvez essayer de courir avec while (true) { var i = 'yo'; } while (true) { var i = 'yo'; } dans la console. (Attention: cela va vous rendre sortingste)

3) L’état à l’intérieur des fonctions JS est invisible pour les navigateurs

Parce que le navigateur ne peut pas s’interrompre au milieu d’une fonction JS, cela signifie qu’il ne peut jamais connaître aucun état intervenant à mi-parcours de ladite fonction. Le navigateur ne peut agir qu’en fonction de l’état qui rest une fois la fonction terminée. Pas clair? Pour illustrer:

 var someGlobalValue = null; function lol() { someGlobalValue = 'hi'; someGlobalValue = 'hello'; someGlobalValue = 'ok'; } 

Lorsque la fonction lol est exécutée, someGlobalValue assume plusieurs valeurs, mais le navigateur n’est conscient que de la dernière , car il devra s’interposer à mi-parcours pour voir les autres (ce qu’il ne peut pas faire!)

4) L’état CSS dans les fonctions JS est également invisible pour les navigateurs.

La même chose s’applique à l’état css! (Et maintenant, vous voyez peut-être que je commence à répondre à votre question).

Si vous appelez la fonction suivante:

 function lol() { $('.thing').css('left', '10px'); $('.thing').css('left', '30px'); } 

Le navigateur n’appliquera jamais la valeur left: 10px car aucune action n’est entreprise au milieu d’une fonction! Seuls les résultats d’une fonction, complète, peuvent être utilisés par le navigateur.

Répondre à vos questions !!

violon 1

La classe left_more est ajoutée immédiatement après la classe de left – le navigateur ne voit jamais la classe de left et applique le style css à la fin de la fonction – en appliquant la classe left_more , mais comme aucune valeur initiale de gauche n’était présente, il n’y a pas d’animation. (Le css cascade; tant que les deux classes sont présentes, left_more écrase complètement à left )

violon 2

Même problème – la classe de left est écrasée avant que le navigateur ne puisse la traiter.

violon 3

Cela fonctionne parce que la valeur est définie avec un appel à css et n’est PAS écrasée car addClass est utilisé pour définir l’emplacement où la valeur doit être animée. Le console.log n’est pas pertinent – console.log appel de la fonction css est important. Une fois cette fonction terminée, il y a 2 informations, 1 étant la valeur css , l’autre étant la valeur de class . Cela contraste avec l’autre exemple où il ne rest plus qu’une information après l’exécution de la fonction: la valeur de la class .

Si vous voulez travailler uniquement avec des classes et continuer à lancer la transition, le stream devrait ressembler à ceci:

1) Ajouter la classe de left 2) Fonction de sortie, qui permet au navigateur d’afficher l’état 3) Ajouter la classe de left_more

Sry pour l’essai lol. Mais je pense que cela nécessitait une longue explication à cause de la subtilité du problème.

Plusieurs problèmes se posent ici. Dans les exemples donnés, la raison pour laquelle la transition ne se produit pas lorsque la première classe de left est ajoutée est due au fait que pour que le moteur de rendu anime une propriété, cette propriété doit déjà avoir une valeur. Dans ce cas, il n’y a pas de valeur pour left et, par conséquent, la transition ne se produit pas.

La raison pour laquelle cela ne fonctionne pas lorsqu’il est enchaîné est dû à sa spécificité. jQuery ajoute les deux classes et lorsque l’appel à rendre la page est effectué, la dernière définition ajoutée pour left est appliquée en raison de leur spécificité partagée.

La raison pour laquelle il semble fonctionner en ajoutant la classe à une heure distincte de la chaîne est que le moteur de rendu a été appelé implicitement à partir de jQuery lorsque le fichier console.log a accédé aux valeurs css de l’élément. Stryner a souligné cela dans sa réponse: https://stackoverflow.com/a/33902053/1026459 . C’était une très belle trouvaille.

Voici un exemple de ce qui est appliqué pour que la valeur de left n’ait pas besoin d’être devinée.

La viande de ce qui se passe est que le décalage de l’élément est trouvé pour obtenir le décalage de pixel pour la gauche. Ensuite, cette valeur est appliquée à la propriété de style de gauche. À ce stade, alors que l’élément n’a toujours pas changé de position, le moteur de rendu est appelé pour mettre à jour la propriété left. La propriété est ensuite supprimée pour s’assurer que la spécificité n’est pas prioritaire sur la définition de classe, puis la définition de classe est appliquée. Cela facilitera la transition lors de la première rencontre.

jsFiddle Demo

 $('button').click(function() { $('div').css({'transition':'left 1000ms'}).each(function(){ $(this).css('left',$(this).offset().left); window.getComputedStyle(this,null).getPropertyValue("left"); }).css('left','').addClass('left'); }); 
 button { margin-top: 30px; } div { position: absolute; width: 10px; height: 10px; background-color: red; } .left { left: 100px; } .left_more { left: 400px; }