animation addClass / removeClass avec jQuery

226

J'utilise jQuery et jQuery-ui et je souhaite animer divers attributs sur divers objets.

Pour expliquer le problème ici, je l'ai simplifié en une div qui passe du bleu au rouge lorsque l'utilisateur passe la souris dessus.

Je peux obtenir le comportement que je souhaite lors de l'utilisation animate(), mais lorsque je le fais, les styles que j'anime doivent être dans le code d'animation et sont donc séparés de ma feuille de style. (voir exemple 1 )

Une alternative utilise addClass()et removeClass()mais je n'ai pas pu recréer le comportement exact que je peux obtenir animate(). (voir exemple 2 )


Exemple 1

Jetons un œil au code que j'ai avec animate():

$('#someDiv')
  .mouseover(function(){
    $(this).stop().animate( {backgroundColor:'blue'}, {duration:500});
  })
  .mouseout(function(){
    $(this).stop().animate( {backgroundColor:'red'}, {duration:500});
  });

il affiche tous les comportements que je recherche:

  1. S'anime en douceur entre le rouge et le bleu.
  2. Aucune animation de «file d'attente excessive» lorsque l'utilisateur déplace rapidement sa souris dans et hors de la div.
  3. Si l'utilisateur déplace sa souris vers l'extérieur / vers l'intérieur pendant que l'animation est en cours de lecture, il se déplace correctement entre l'état «à mi-chemin» actuel et le nouvel état «objectif».

Mais comme les changements de style sont définis dans, animate()je dois changer les valeurs de style là-bas, et je ne peux pas simplement le faire pointer vers ma feuille de style. Cette «fragmentation» de la définition des styles est quelque chose qui me dérange vraiment.


Exemple 2

Voici ma meilleure tentative actuelle en utilisant addClass()et removeClass(notez que pour que l'animation fonctionne, vous avez besoin de jQuery-ui):

//assume classes 'red' and 'blue' are defined

$('#someDiv')
  .addClass('blue')
  .mouseover(function(){
    $(this).stop(true,false).removeAttr('style').addClass('red', {duration:500});
  })
  .mouseout(function(){
    $(this).stop(true,false).removeAttr('style').removeClass('red', {duration:500});
  });

Cela présente à la fois la propriété 1. et 2. de mes exigences d'origine, mais 3 ne fonctionne pas.

J'en comprends la raison:

Lors de l'animation addClass()et removeClass()jQuery ajoute un style temporaire à l'élément, puis incrémente les valeurs appropriées jusqu'à ce qu'elles atteignent les valeurs de la classe fournie, et alors seulement, il ajoute / supprime réellement la classe.

Pour cette raison, je dois supprimer l'attribut style, sinon, si l'animation est arrêtée à mi-chemin, l'attribut style resterait et remplacerait définitivement toutes les valeurs de classe, car les attributs de style dans une balise ont une importance plus élevée que les styles de classe.

Cependant, lorsque l'animation est à mi-chemin, elle n'a pas encore ajouté la nouvelle classe, et avec cette solution, la couleur passe à la couleur précédente lorsque l'utilisateur déplace sa souris avant la fin de l'animation.


Ce que je veux idéalement, c'est pouvoir faire quelque chose comme ça:

$('#someDiv')
  .mouseover(function(){
    $(this).stop().animate( getClassContent('blue'), {duration:500});
  })
  .mouseout(function(){
    $(this).stop().animate( getClassContent('red'), {duration:500});
  });

getClassContentretournerait simplement le contenu de la classe fournie. Le point clé est que de cette façon, je n'ai pas à conserver mes définitions de style partout, mais je peux les conserver dans les classes de ma feuille de style.

Johannes
la source
1
Quelles versions d'IE devez-vous prendre en charge? Seriez-vous satisfait d'IE9? Ou avez-vous besoin de soutenir plus bas?
tw16
1
Pour être honnête, je ne me soucie pas du tout d'IE. Tout cela a été testé avec les navigateurs webkit uniquement (safari / chrome).
Johannes
à quoi getClassContentressemble
sreginogemoh

Réponses:

311

Puisque vous n'êtes pas inquiet pour IE, pourquoi ne pas simplement utiliser des transitions css pour fournir l'animation et jQuery pour changer les classes. Exemple en direct: http://jsfiddle.net/tw16/JfK6N/

#someDiv{
    -webkit-transition: all 0.5s ease;
    -moz-transition: all 0.5s ease;
    -o-transition: all 0.5s ease;
    transition: all 0.5s ease;
}
tw16
la source
14
Depuis le 2015-06-12, cela est pris en charge dans - IE 10+ - Chrome 26+ - FireFox 16+ - Safari 6.1+ - Opera 12.1+ -webkit, -moz, -o n'est nécessaire que pour les navigateurs encore plus anciens. Vous pouvez probablement le laisser de côté pour économiser de l'espace.
2015
3
@clst, je préférerais la rétrocompatibilité avec les anciens navigateurs plutôt que d'économiser quelques octets d'espace.
Arman H
96

Une autre solution (mais elle nécessite jQueryUI comme l'a souligné Richard Neil Ilagan dans les commentaires): -

addClass, removeClass et toggleClass acceptent également un deuxième argument; la durée nécessaire pour passer d'un état à l'autre.

$(this).addClass('abc',1000);

Voir jsfiddle: - http://jsfiddle.net/6hvZT/1/

Omar Tariq
la source
28
Notez que cela nécessite jQuery UI. jQuery prêt à l'emploi ne prend pas en charge l'interpolation d'animation pour les xxxClass()fonctions.
Richard Neil Ilagan
@Richard Neil Ilagan: Merci d'avoir notifié. J'ai vraiment raté ce point.
Omar Tariq
4
Pouvez-vous indiquer quel fichier télécharger et inclure dans le fichier .html afin que je puisse utiliser jQueryUI uniquement pour l' xxxClassinterpolation d'animation de cette façon?
nitrate de sodium
[jqueryui.com] (jqueryui.com) @sodiumnitrate
joe_young
1
Cette solution n'anime pas non plus de la même manière que slide () ou animate (). La valeur en millisecondes est un délai, qui n'est pas une animation.
Solona Armstrong
38

Vous pouvez utiliser l'interface utilisateur de jquery switchClass, Heres un exemple:

$( "selector" ).switchClass( "oldClass", "newClass", 1000, "easeInOutQuad" );

Ou voir ce jsfiddle .

by0
la source
1
-1. Vous n'avez pas respecté les restrictions 1, 2 et 3 que j'ai énumérées dans le message d'origine. Plus précisément, switchClass gère mal les exigences 2 et 3.
Johannes
12

Vous avez juste besoin du noyau d'effets jQuery UI (13 Ko), pour activer la durée de l'ajout (tout comme Omar Tariq l'a souligné)

Patrick
la source
5

J'examinais cela, mais je voulais avoir un taux de transition différent pour les entrées et les sorties.

C'est ce que j'ai fini par faire:

//css
.addedClass {
    background: #5eb4fc;
}

// js
function setParentTransition(id, prop, delay, style, callback) {
    $(id).css({'-webkit-transition' : prop + ' ' + delay + ' ' + style});
    $(id).css({'-moz-transition' : prop + ' ' + delay + ' ' + style});
    $(id).css({'-o-transition' : prop + ' ' + delay + ' ' + style});
    $(id).css({'transition' : prop + ' ' + delay + ' ' + style});
    callback();
}
setParentTransition(id, 'background', '0s', 'ease', function() {
    $('#elementID').addClass('addedClass');
});

setTimeout(function() {
    setParentTransition(id, 'background', '2s', 'ease', function() {
        $('#elementID').removeClass('addedClass');
    });
});

Cela transforme instantanément la couleur d'arrière-plan en # 5eb4fc, puis revient lentement à la normale en 2 secondes.

Voici un violon

Tj Gienger
la source
2

Bien que la question soit assez ancienne, j'ajoute des informations non présentes dans les autres réponses.

L'OP utilise stop () pour arrêter l'animation en cours dès la fin de l'événement. Cependant, l'utilisation de la bonne combinaison de paramètres avec la fonction devrait aider. par exemple. stop (vrai, vrai) ou stop (vrai, faux) car cela affecte bien les animations en file d'attente.

Le lien suivant illustre une démo qui montre les différents paramètres disponibles avec stop () et comment ils diffèrent de finish ().

http://api.jquery.com/finish/

Bien que l'OP n'ait eu aucun problème lors de l'utilisation de JqueryUI, cela s'adresse à d'autres utilisateurs qui peuvent rencontrer des scénarios similaires mais ne peuvent pas utiliser JqueryUI / doivent également prendre en charge IE7 et 8.

Anurag
la source