animando addClass / removeClass con jQuery


226

Sto usando jQuery e jQuery-ui e voglio animare vari attributi su vari oggetti.

Per motivi di spiegazione del problema qui, l'ho semplificato in un div che cambia da blu a rosso quando l'utente passa il mouse su di esso.

Sono in grado di ottenere il comportamento che desidero durante l'utilizzo animate(), tuttavia quando lo faccio gli stili che sto animando devono essere nel codice di animazione e quindi sono separati dal mio foglio di stile. (vedi esempio 1 )

Un'alternativa sta usando addClass()e removeClass()ma non sono stato in grado di ricreare il comportamento esatto che posso ottenere animate(). (vedi esempio 2 )


Esempio 1

Diamo un'occhiata al codice che ho con animate():

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

mostra tutti i comportamenti che sto cercando:

  1. Si anima uniformemente tra rosso e blu.
  2. Nessuna animazione "sovrascrittura" quando l'utente sposta rapidamente il mouse dentro e fuori dal div.
  3. Se l'utente sposta il mouse verso l'esterno / verso l'interno mentre l'animazione è ancora in esecuzione, si sposta correttamente tra lo stato corrente "a metà strada" e il nuovo stato "obiettivo".

Ma poiché i cambiamenti di stile sono definiti in animate()Devo cambiare lì i valori di stile e non posso semplicemente farli puntare al mio foglio di stile. Questo "frammento" di dove sono definiti gli stili è qualcosa che mi disturba davvero.


Esempio 2

Ecco il mio miglior tentativo attuale usando addClass()e removeClass(nota che per far funzionare l'animazione hai bisogno di 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});
  });

Questo mostra sia la proprietà 1. che la 2. dei miei requisiti originali, tuttavia 3 non funziona.

Capisco il motivo di questo:

Durante l'animazione addClass() e removeClass()jQuery aggiungono uno stile temporaneo all'elemento, quindi incrementa i valori appropriati fino a quando non raggiungono i valori della classe fornita e solo allora aggiunge / rimuove effettivamente la classe.

Per questo motivo devo rimuovere l'attributo di stile, altrimenti se l'animazione viene interrotta a metà l'attributo di stile rimarrebbe e sovrascriverebbe in modo permanente qualsiasi valore di classe, poiché gli attributi di stile in un tag hanno un'importanza maggiore rispetto agli stili di classe.

Tuttavia, quando l'animazione è terminata a metà strada non ha ancora aggiunto la nuova classe, e quindi con questa soluzione il colore passa al colore precedente quando l'utente sposta il mouse prima che l'animazione sia completata.


Quello che voglio idealmente è poter fare qualcosa del genere:

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

Dove getClassContentrestituirebbe semplicemente il contenuto della classe fornita. Il punto chiave è che in questo modo non devo mantenere le mie definizioni di stile ovunque, ma posso tenerle in classe nel mio foglio di stile.


1
Quali versioni di IE devi supportare? Saresti felice con IE9? O hai bisogno di supporto inferiore?
tw16,

1
Ad essere sincero, non mi preoccupo affatto di IE. Tutto questo è stato testato solo con i browser webkit (safari / chrome).
Johannes,

com'è getClassContent?
sreginogemoh,

Risposte:


311

Dato che non sei preoccupato per IE, perché non usare semplicemente le transizioni css per fornire l'animazione e jQuery per cambiare le classi. Esempio live: 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;
}

14
A partire dal 12/06/2015 questo è supportato in - IE 10+ - Chrome 26+ - FireFox 16+ - Safari 6.1+ - Opera 12.1+ -webkit, -moz, -o è necessario solo per browser ancora più vecchi. Probabilmente puoi lasciarlo fuori per risparmiare spazio.
cl

3
@clst, preferirei la retrocompatibilità con i vecchi browser piuttosto che risparmiare qualche byte di spazio.
Arman H,

96

Un'altra soluzione (ma richiede jQueryUI come sottolineato da Richard Neil Ilagan nei commenti): -

addClass, removeClass e toggleClass accetta anche un secondo argomento; la durata del tempo per passare da uno stato all'altro.

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

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


28
Si noti che ciò richiede l'interfaccia utente di jQuery. jQuery out of the box non supporta l'interpolazione di animazione per le xxxClass()funzioni.
Richard Neil Ilagan,

@Richard Neil Ilagan: Grazie per avermelo avvisato. Mi mancava davvero quel punto.
Omar Tariq,

4
Puoi indicare quale file scaricare e includere nel file .html in modo da poter utilizzare jQueryUI solo per l' xxxClassinterpolazione di animazioni in questo modo?
Sodio nitrato

[jqueryui.com] (jqueryui.com) @sodiumnitrate
joe_young

1
Questa soluzione inoltre non si anima allo stesso modo di slide () o animate (). Il valore in millisecondi è un ritardo, che non è un'animazione.
Solona Armstrong,

38

Puoi usare jquery ui's switchClass, ecco un esempio:

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

O vedi questo jsfiddle .


1
-1. Non hai soddisfatto le restrizioni 1, 2 e 3 che ho elencato nel post originale. In particolare switchClass gestisce male i requisiti 2 e 3.
Johannes,

12

Hai solo bisogno di jQuery UI effects-core (13KB), per abilitare la durata dell'aggiunta (proprio come Omar Tariq ha sottolineato)


5

Stavo esaminando questo, ma volevo avere un diverso tasso di transizione per entrare e uscire.

Questo è quello che ho finito per fare:

//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');
    });
});

Questo trasforma immediatamente il colore di sfondo in # 5eb4fc e poi lentamente torna alla normalità per oltre 2 secondi.

Ecco un violino


2

Sebbene la domanda sia piuttosto vecchia, sto aggiungendo informazioni non presenti in altre risposte.

L'OP utilizza stop () per interrompere l'animazione corrente non appena l'evento viene completato. Tuttavia, l'utilizzo del giusto mix di parametri con la funzione dovrebbe aiutare. per esempio. stop (vero, vero) o stop (vero, falso) poiché ciò influenza bene le animazioni in coda.

Il seguente link illustra una demo che mostra i diversi parametri disponibili con stop () e come differiscono da finish ().

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

Sebbene l'OP non abbia avuto problemi con l'utilizzo di JqueryUI, questo è per altri utenti che potrebbero imbattersi in scenari simili ma non possono usare JqueryUI / necessitare di supportare anche IE7 e 8.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.