números animadas (semi-contagem decrescente) com jQuery?
-
06-07-2019 - |
Pergunta
Eu estou tentando fazer um valor numérico, digamos 5000, mudar rapidamente para outro valor, digamos, 4000, usando JQuery. Agora eu faço isso muito bem usando:
mod(".class",4000,"add");
function mod(id,value,type){
var numb = $(id).html();
var current_value = parseInt(numb);
do {
if(type == "add")
increment(id);
else
decrement(id);
current_value = parseInt(numb);
}while(current_value != value);
function decrement(id){
$(id).html(current_value-1);
}
function increment(id){
$(id).html(current_value+1);
}
}
Eu sei que não é provavelmente a melhor maneira de ir sobre isso, mas o que eu preciso para que ele faça é contagem decrescente (ou para cima) os números muito rapidamente a partir do valor atual para o valor definido. O que eu pretendia com este método era ter um atraso usando setInterval ou setTimeout, porém, que faz com que todo o script falhar muito mal.
Qualquer conselho é apreciado, no entanto eu preferiria não usar grandes plugins para esta tarefa aparentemente simples.
Solução
Quando eu corri o código fornecido, eu fui pego em um loop infinito. No final do loop faz, você tem
current_value = parseInt(numb);
mas o valor de dormentes só é definido no início da função, por isso vai durar para sempre. Se você mudar isso para
current_value = parseInt($(id).html());
, em seguida, ele funciona bem. Exceto que ele parece acontecer instantaneamente.
Eu cortei-se um método para alcançar a animação usando o tempo limite que parece funcionar razoavelmente bem, mas como eu ainda sou bastante novo para JavaScript Eu não sei se há uma abordagem mais eficiente ou não. Apenas ajustar o segundo param passado para setTimeout para obter a velocidade desejada. E se você quiser alterar o valor de incremento / decréscimo, basta alterar a desaceleração da dir
.
function mod2(id, value) {
var numb = $(id).html();
var current_value = parseInt(numb);
// determine direction to go
var dir = 1;
if (current_value - value > 0) {
dir *= -1;
}
getThere(id, current_value, value, dir);
}
function getThere(id, current_value, target_value, dir) {
current_value += dir;
$(id).html(current_value);
if (current_value != target_value) {
setTimeout("getThere('"+id+"',"+current_value+","+target_value+","+dir+")", 10);
}
}
Outras dicas
O que você está fazendo aqui é atualizar o DOM muitas vezes em rápida sucessão. Como resultado, o navegador irá esperar até que tenha feito todas as suas alterações, e só então irá re-desenhar a página. Assim, você não vai conseguir ver qualquer mudança visual até que o número vai todo o caminho até 4000.
Sim, você precisa usar um setTimeout
ou setInterval
/ clearInterval
. Ou, para maior clareza do código, você poderia usar o jQuery "espera" plug-in :
// (code to get new value goes here)
$('.class').wait(100, function(){
$(this).text(newValue);
});
Em vez de html()
, eu tenho text()
usado, uma vez que parece que você não precisa alterar qualquer estrutura HTML.
Eu gosto de abordagem de espinho com setTimeout, mas eu gostaria de condensá-lo para baixo para 2 funções e iniciá-lo após o carregamento da janela para garantir a página foi carregada antes de atualizar o contador:
var counterTimeout = 10; // time between increments in ms
$(window).load(function() {
mod('class', 'add', 4000);
});
function mod(class, type, targetVal) {
var $class = $(class);
var numb = parseInt($class.html());
numb = (type == 'add') ? numb + 1 : numb - 1;
$class.html(numb);
if (numb != targetVal) {
setTimeout('mod("' + class + '","' + type + '",' + targetVal)', counterTimeout);
}
}
O caso base não está satisfeita no caso $ class.html () começa com um valor maior do que o targetVal no caso de 'Adicionar' ou inferior ao targetVal no outro caso. Você teria que garantir que isso não aconteça antes de fazer a chamada de função.