jQuery / .animate() — Criar efeitos personalizados
.animate() muda propriedades CSS atuais até os alvos ao longo do tempo. .animate({ left: 100, width: 160, opacity: 0.4 }) modifica posição, largura e opacidade juntas. Duração e easing controlam o percurso; a conclusão é chamada por elemento.
Propriedades e duração
O primeiro argumento .animate() contém alvos. left e width numéricos são pixels aqui; opacity não tem unidade e vai de zero a um. Um objeto muda simultaneamente; chamadas separadas entram normalmente na fila.
left precisa de posição diferente de static. relative desloca desde a origem, não para x=100 do documento. width mede conteúdo; content-box simples evita condições extras de borda e padding.
duration é em milissegundos, padrão 400. Easing muda velocidade: swing e linear atingem os mesmos alvos. Não suponha interpolação de qualquer cor ou transform pelo jQuery básico; confira propriedades numéricas aceitas.
Exemplo completo com dois elementos
Salve UTF-8 animate-demo.html e abra. A Internet carrega a versão completa oficial 4.0.0. Animação temporizada precisa de effects, não Slim. Não precisa de servidor nem pacotes. Intermediários, alvos, parada e repetição foram conferidos no Edge para Windows com 3.7.1 e 4.0.0.
As caixas compartilham alvos. Start restaura valores iniciais. Reset mantém duração/easing e restaura caixas e contadores. Durante execução outro início é bloqueado.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Animate CSS properties and observe completion</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
body { font: 16px/1.6 sans-serif; max-width: 760px; margin: 20px; }
label { display: block; margin: 8px 0; }
select, button { font: inherit; margin: 4px; }
#stage { background: #eef4f4; padding: 10px; overflow-x: auto; }
.box { position: relative; left: 0; width: 80px; height: 45px; margin: 12px 0; background: teal; color: white; box-sizing: content-box; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<label>Duration <select id="duration"><option value="600">600ms</option><option value="1200">1200ms</option><option value="0">0ms</option></select></label>
<label>Easing <select id="easing"><option value="swing">swing</option><option value="linear">linear</option></select></label>
<button type="button" id="start">Start</button>
<button type="button" id="stop">Stop here</button>
<button type="button" id="reset">Reset</button>
<div id="stage"><div class="box" id="alpha">Alpha</div><div class="box" id="beta">Beta</div></div>
<pre id="result" aria-live="polite"></pre>
<script>
jQuery(function ($) {
const $boxes = $("#stage > .box");
let generation = 0, busy = false, state = "ready", completed = 0, batches = 0;
function report() {
const values = $boxes.map(function () {
const $box = $(this);
return this.id + ": left=" + Math.round(parseFloat($box.css("left"))) + "; width=" + Math.round($box.width()) + "; opacity=" + Number(parseFloat($box.css("opacity")).toFixed(2));
}).get();
$("#result").text(["state=" + state, "completed=" + completed + "; batches=" + batches, ...values].join("\n"));
}
function reset() {
generation++; $boxes.stop(true, false).css({ left: 0, width: 80, opacity: 1 });
busy = false; state = "ready"; completed = batches = 0;
$("#start").prop("disabled", false); report();
}
$("#start").on("click", function () {
if (busy) return;
reset(); busy = true; state = "running"; $(this).prop("disabled", true);
const run = generation;
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const duration = reduce ? 0 : Number($("#duration").val());
$boxes.animate({ left: 100, width: 160, opacity: 0.4 }, {
duration: duration, easing: $("#easing").val(),
complete: function () { if (run === generation) { completed++; report(); } }
});
$boxes.promise("fx").done(function () {
if (run !== generation) return;
batches++; busy = false; state = "done";
$("#start").prop("disabled", false); report();
});
report();
});
$("#stop").on("click", function () {
if (!busy) return;
generation++; $boxes.stop(true, false);
busy = false; state = "stopped"; $("#start").prop("disabled", false); report();
});
$("#reset").on("click", reset);
reset();
});
</script>
</body>
</html>
Início: largura 80, left relativo zero e opacidade um. Arredondar exibição não limita o cálculo a inteiros.
state=ready
completed=0; batches=0
alpha: left=0; width=80; opacity=1
beta: left=0; width=80; opacity=1
- Start com 600ms e swing: três propriedades mudam juntas.
- Final: state=done, completed=2; batches=1 ; ambas left=100; width=160; opacity=0.4.
- Reset, mude só easing para linear e compare. Os alvos são iguais.
- Com 1200ms, Stop here mantém intermediários em state=stopped, sem done posterior.
- Reset e repita. 0ms alcança alvos e contadores imediatamente.
- Movimento reduzido também conclui imediatamente apesar de 1200ms escolhido.
Conclusão individual e coletiva
complete é chamado duas vezes e this é o nó correspondente. Um callback não conclui o conjunto. .animate() não bloqueia JavaScript até terminar.
.promise("fx") observa trabalho do conjunto. Aqui incrementa batches uma vez e habilita Start. Tarefas extras da fila padrão podem ampliar a espera.
Fila vazia não comprova conclusão natural. .stop(true, false) pode esvaziar no meio e resolver a promessa fx. Stop e Reset mudam generation primeiro para callbacks antigos não substituírem cancelamento por done.
Chamadas repetidas costumam acumular efeitos; desabilitar e busy evitam isso. Redirecionar da posição atual exige outra política explícita.
Parada, restauração e layout
jumpToEnd=false mantém valores atuais. Reset define três propriedades; intermediários antigos mudariam a comparação.
prefers-reduced-motion reduce usa zero nesta execução com mesmo alvo e conclusão, sem mudar configuração global.
Posição e largura afetam arredores e sobreposição: confira tela estreita, zoom, texto longo e contêineres de rolagem. Opacidade zero não implica display:none nem ocultação acessível.
Evite transições CSS ou plugins controlando as mesmas propriedades ao mesmo tempo. Defina responsabilidade de elementos, propriedades e filas e limite seletores e eventos à função.




