animando addClass / removeClass com jQuery

Eu estou usando jQuery e jQuery-ui e quero animar vários atributos em vários objects.

Por uma questão de explicar o problema aqui eu simplifiquei para um div que muda de azul para vermelho quando o usuário mouses sobre ele.

Eu sou capaz de obter o comportamento que eu quero quando usando animate() , no entanto, ao fazê-lo, os estilos que estou animando tem que estar no código de animação e por isso são separados da minha folha de estilo. (veja o exemplo 1 )

Uma alternativa é usar addClass() e removeClass() mas não consegui recriar o comportamento exato que posso obter com animate() . (veja o exemplo 2 )


Exemplo 1

Vamos dar uma olhada no código que tenho com animate() :

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

exibe todos os comportamentos que estou procurando:

  1. Anima suavemente entre vermelho e azul.
  2. Nenhuma animação ‘overqueue-ing’ quando o usuário move o mouse rapidamente para dentro e para fora do div.
  3. Se o usuário mover o mouse para fora / para dentro enquanto a animação ainda está sendo reproduzida, ele fica mais fácil entre o estado atual ‘intermediário’ e o novo estado ‘objective’.

Mas como as mudanças de estilo são definidas no animate() eu tenho que mudar os valores de estilo lá, e não posso apenas apontar para a minha folha de estilo. Essa ‘fragmentação’ de onde os estilos são definidos é algo que realmente me incomoda.


Exemplo 2

Aqui está a minha melhor tentativa atual usando addClass() e removeClass (note que para a animação funcionar você precisa do jQuery-ui):

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

Isto exibe tanto a propriedade 1. como 2. das minhas necessidades originais, no entanto, 3 não funciona.

Eu entendo a razão para isso:

Ao animar addClass() e removeClass() jQuery adiciona um estilo temporário ao elemento e, em seguida, incrementa os valores apropriados até que eles alcancem os valores da class fornecida, e somente então ele realmente adiciona / remove a class.

Devido a isso, preciso remover o atributo style, caso contrário, se a animação for interrompida, o atributo style permanecerá e sobrescreverá permanentemente quaisquer valores de class, pois os atributos de estilo em uma tag têm maior importância do que os estilos de class.

No entanto, quando a animação está na metade do caminho, ela ainda não adicionou a nova class, e assim, com essa solução, a cor salta para a cor anterior quando o usuário move o mouse antes que a animação seja concluída.


O que eu quero idealmente é ser capaz de fazer algo assim:

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

Onde getClassContent apenas retornaria o conteúdo da class fornecida. O ponto chave é que desta forma eu não tenho que manter minhas definições de estilo em todo o lugar, mas posso mantê-las em classs na minha folha de estilo.

Como você não está preocupado com o IE, por que não apenas usar transições CSS para fornecer a animação e o jQuery para alterar as classs. Exemplo ao vivo: 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; } 

Outra solução (mas requer jQueryUI como apontado por Richard Neil Ilagan nos comentários): –

addClass, removeClass e toggleClass também aceita um segundo argumento; a duração do tempo para ir de um estado para o outro.

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

Veja jsfiddle: – http://jsfiddle.net/6hvZT/1/

Você poderia usar o switchClass do jquery ui, Heres um exemplo:

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

Ou veja este jsfiddle .

Você só precisa do jQuery UI effects-core (13KB), para ativar a duração da adição (assim como Omar Tariq apontou)

Eu estava olhando para isso, mas queria ter uma taxa de transição diferente para entrar e sair.

Foi o que acabei fazendo:

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

Isso instantaneamente transforma a cor de fundo em # 5eb4fc e, em seguida, desbota lentamente de volta ao normal por mais de 2 segundos.

Aqui está um violino

Embora a questão seja bastante antiga, estou adicionando informações que não estão presentes em outras respostas.

O OP está usando stop () para interromper a animação atual assim que o evento for concluído. No entanto, usar a combinação correta de parâmetros com a function deve ajudar. por exemplo. stop (true, true) ou stop (true, false), pois isso afeta bem as animações enfileiradas.

O link a seguir ilustra uma demonstração que mostra os diferentes parâmetros disponíveis com stop () e como eles diferem de finish ().

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

Embora o OP não tenha problemas ao usar o JqueryUI, isso é para outros usuários que podem se deparar com cenários semelhantes, mas não podem usar o JqueryUI / precisam suportar o IE7 e 8 também.