Ignorer la transition et modifier une propriété instantanément

Je souhaite contourner la transition CSS et modifier une propriété instantanément.
J'ai essayé de régler la transition-duration de transition-duration à 0s avant la modification, puis de régler la transition-duration à sa valeur d'origine:

 $('div').css('width', '200px').delay(1000).queue(function() { $(this).css({ transitionDuration: '0s', msTransitionDuration: '0s', mozTransitionDuration: '0s', webkitTransitionDuration: '0s', oTransitionDuration:'0s' }).css('width', '10px').css({ transitionDuration: '2s', msTransitionDuration: '2s', mozTransitionDuration: '2s', webkitTransitionDuration: '2s', oTransitionDuration:'2s' }) })​ 

Violon
Cela ne fonctionne évidemment pas.

Je comprends que la spécification ne définisse pas ce comportement pour ceci:

Étant donné que cette spécification ne définit pas lorsque les valeurs calculées changent et, par conséquent, les modifications apportées aux valeurs calculées sont considérées comme simultanées, les auteurs doivent être conscients que la modification de l'une des propriétés de transition peu de temps après avoir effectué une modification pouvant être modifiée peut entraîner un comportement qui Varie entre les implémentations, car les modifications peuvent être considérées comme simultanées dans certaines implémentations mais pas dans d'autres.

Y a-t-il un moyen facile de faire ceci?

Remarque: La propriété que je change est de transform .animate() ne serait pas une option.

Comme personne d'autre n'a posté de réponse valide, voici:

 $('div').css('width', '200px').delay(1000).queue(function() { $(this).css({transition: '0s', width: '10px'}).delay(1).queue(function() { $(this).css({transition:'2s'}); }); },1000)​; 

VIOLON

Ou si c'est l'inverse:

 $('div').css({ transition: '0s' }).css('width', '200px').delay(1000).queue(function() { $(this).css({width: '10px', transition: '2s'}); }); 

VIOLON

JQuery devrait normaliser les préfixes des fournisseurs ces jours-ci, de sorte que vous ne devez pas les dactylographier tous vous-même.


Le problème ici est que jQuery attache tous les styles à la fois, en gardant les derniers styles, en écrasant les styles précédents de la même propriété CSS sans jamais faire un repeint du DOM, et les tests avec javascript natif semblent faire la même chose, Donc, c'est probablement le navigateur essayant d'éviter les reflets non-cédants en ajoutant un style juste pour l'avoir changé dans la prochaine ligne de code, ce qui fait:

 $('div').css({ transition: '0s', width: 200 }).css({ transition: '3s', width: 10 }); 

Ne fonctionnera pas car seul le dernier style est ajouté.

C'est là que delay() entre en jeu, la question de l'OP était déjà en utilisant delay() donc il n'y avait aucune raison de ne pas l'utiliser, mais le retrait du delay() entraînera bien sûr le problème ci-dessus, où le navigateur ne peint pas le Premier style, mais seulement le dernier etc.

Comme delay() n'est vraiment qu'un délai d'attente, il efface efficacement l'exécution du deuxième paramètre des styles, provoquant deux décalcomanies de navigateur.

Étant donné qu'il s'agit probablement d'un problème de navigateur, et pas quelque chose que nous pouvons changer, le fait de différer le paramètre du deuxième style est la seule façon de le faire fonctionner, et l'utilisation d'un délai fonctionnera encore, même si elle est configurée à seulement 1 millisecondé, ou une Pourrait différer l'exécution avec un timeout régulier, qui est la manière habituelle de reporter l'exécution d'un script:

 $('div').css({ transition: '0s', width: 200 }); setTimeout(function() { $('div').css({ transition: '3s', width: 10 }); }); 

VIOLON

Ce qui précède fonctionnera très bien, car le délai d'attente entraîne le premier réglage du style à être peint par le navigateur, et plus tard le réglage du style dans le délai d'attente, mais comme aucun temps n'est défini, il est exécuté aussi tôt Car le navigateur peut (mais encore différé jusqu'à ce que le script actuel soit terminé), qui, pour l'œil humain, semblerait immédiatement, et cela résout le problème.

Si vous avez le contrôle du CSS

La chose la plus simple à faire est de lier l'animation à une certaine classe, puis, à quel point vous souhaitez que l'animation ne soit plus contournée, vous ajoutez la classe, sinon aucune animation n'est jamais définie. Si l'inverse, vous voulez généralement l'animation, mais vous souhaitez parfois la contourner, puis ajouter la classe par défaut et la supprimer au moment du contournement.

Exemple CSS

 div{ height: 100px; width: 200px; background: red; } div.doTransition { width: 10px; transition: width 2s linear; -ms-transition: width 2s linear; -moz-transition: width 2s linear; -webkit-transition: width 2s linear; -o-transition: width 2s linear; } 

Voir le violon qui crée un événement de clic pour démarrer l'animation quand on le souhaite, mais ce pourrait être un autre déclencheur programmatique pour ajouter la classe au moment où l'on ne veut plus le contourner. Ce violon fait le contraire , il suppose que l'animation est présente, mais la charge de la page immédiatement la contourne en supprimant la classe.

Configurez une classe de suppression qui désactivera les transitions css sur un élément appliqué !important est parfait pour cela:

 .notransition { -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; -ms-transition: none !important; transition: none !important; } 

Vous pouvez maintenant toggleClass pour toggleClass le comportement souhaité (transition en douceur contre changement instantané):

 $('div'). toggleClass('notransition', true). //or false! css('width', '200px'); 

Fiddled . IMO l'un des avantages de cette approche est que vous avez une séparation claire entre le style d'élément par défaut et le drapeau de désactivation de toutes les animations en douceur . C'est aussi une approche réutilisable très "enveloppante", c'est-à-dire que vous pouvez facilement ajouter une propriété booléenne facultative à vos méthodes existantes qui indiqueraient s'il faut ou non exécuter des transitions.

NB: parfois, vous voudrez peut-être désactiver les transitions sur la page pour toutes les raisons de performance / UX. Dans ce cas, vous pouvez changer le sélecteur vers .notransition * et désactiver la transition sur tous les éléments descendants.

La question est que, puisqu'il n'y a aucune raison pour que le navigateur ralentisse et exécute chaque opération séparément, il les combine et fait les deux en même temps. La recherche de offsetHeight est une façon de l'obliger à effectuer chaque opération séparément, car il doit recalculer la hauteur. http://jsfiddle.net/markasoftware/6cTeY/15/ fonctionne parfaitement

C'est la seule façon de pouvoir le faire fonctionner. JQuery semble être un peu têtu.

http://fiddle.jshell.net/8qTpe/1/

PS Il existe des erreurs dans votre approche:

  1. Vous re-dimensionnez à 200px avant le délai, en utilisant les paramètres CSS par défaut.

  2. Vous re-dimensionnez 10px avant le changement de transition vers 2s.

Maintenant, jQuery semble appliquer tous les paramètres CSS d'une filière, c'est pourquoi tout cela ne semble pas fonctionner.

J'irais pour une solution CSS plutôt propre

HTML

 <div id="foo"></div> <button class="out">out</button> <button class="in">in</button> 

JS

 $('button.out').click(function(){console.log($('#foo').addClass);$('#foo').addClass('out')}) $('button.in').click(function(){$('#foo').removeClass('out')}) 

CSS

 div{ height: 100px; width: 10px; background: red; transition: width 0s linear; -ms-transition: width 0s linear; -moz-transition: width 0s linear; -webkit-transition: width 0s linear; -o-transition: width 0s linear; } div.out { width: 200px; transition: width 2s linear; -ms-transition: width 2s linear; -moz-transition: width 2s linear; -webkit-transition: width 2s linear; -o-transition: width 2s linear; } 

http://jsfiddle.net/6cTeY/19/

Je le fais habituellement dans cette mode vanilla JS.

VIOLON

HTML

Supposons que vous ayez un élément

 <div id="element"></div> 

CSS

Supposons que votre élément comporte des transitions CSS déjà actives et de fond: vert

 #element { background: green; width: 200px; height: 200px; -webkit-transition: 'all 0.5s ease-out'; -moz-transition: 'all 0.5s ease-out'; -ms-transition: 'all 0.5s ease-out'; -o-transition: 'all 0.5s ease-out'; } 

JS

L'élément a des transitions CSS, mais nous voulons changer l'arrière-plan de l'élément en BLEU, instantanément.

Juste après cela, nous voulons que le comportement normal de l'élément revienne afin que nous puissions animer son arrière-plan à RED.

Nous devons fermer les transitions pendant un moment et les restaurer tout de suite.

 // grab the element var element = document.getElementById('element'); // removeTransitions element.style.webkitTransition = 'none'; element.style.mozTransition = 'none'; element.style.msTransition = 'none'; element.style.oTransition = 'none'; // apply desired 'instant' property element.style.background = 'blue'; // is applied instantly // this 10ms timeout is necessary for the transitions to be active again setTimeout(function() { element.style.webkitTransition = 'all 5s ease-out'; element.style.mozTransition = 'all 5s ease-out'; element.style.msTransition = 'all 5s ease-out'; element.style.oTransition = 'all 5s ease-out'; // apply desired 'animated' property element.style.background = 'red'; // is applied smoothly }, 10);