Pergunta

Atualmente estou trabalhando em um aplicativo da web que possui uma página que exibe um único gráfico (uma imagem .png).Em outra parte desta página há um conjunto de links que, ao serem clicados, toda a página é recarregada e fica exatamente igual a antes, exceto pelo gráfico no meio da página.

O que eu quero fazer é quando um link é clicado em uma página, apenas o gráfico da página é alterado.Isso irá acelerar tremendamente as coisas, já que a página tem aproximadamente 100 KB e você realmente não deseja recarregar a página inteira apenas para exibi-la.

Tenho feito isso via JavaScript, que funciona até agora, usando o seguinte código

document.getElementById('chart').src = '/charts/10.png';

O problema é que quando o usuário clica no link, pode demorar alguns segundos até que o gráfico mude.Isso faz o usuário pensar que seu clique não fez nada ou que o sistema demora para responder.

O que eu quero que aconteça é exibir um indicador giratório/throbber/status, no lugar de onde a imagem está enquanto está sendo carregada, para que quando o usuário clicar no link ele saiba que pelo menos o sistema recebeu sua entrada e está fazendo algo sobre isso .

Eu tentei algumas sugestões, até mesmo usando um tempo limite psudo para mostrar um botão giratório e, em seguida, voltar para a imagem.

Uma boa sugestão que tive é usar o seguinte

<img src="/charts/10.png" lowsrc="/spinner.gif"/>

O que seria ideal, exceto que o controle giratório é significativamente menor que o gráfico que está sendo exibido.

Alguma outra ideia?

Foi útil?

Solução

Usei algo assim para pré-carregar uma imagem e, em seguida, chamar automaticamente meu javascript quando a imagem terminar de carregar.Você deseja verificar a conclusão antes de configurar o retorno de chamada porque a imagem pode já estar armazenada em cache e pode não chamar seu retorno de chamada.

function PreloadImage(imgSrc, callback){
  var objImagePreloader = new Image();

  objImagePreloader.src = imgSrc;
  if(objImagePreloader.complete){
    callback();
    objImagePreloader.onload=function(){};
  }
  else{
    objImagePreloader.onload = function() {
      callback();
      //    clear onLoad, IE behaves irratically with animated gifs otherwise
      objImagePreloader.onload=function(){};
    }
  }
}

Outras dicas

Você poderia mostrar uma imagem estática que fornecesse a ilusão de ótica de uma roda giratória, como estas.

Usando o carregar() método de jQuery, é facilmente possível fazer algo assim que uma imagem é carregada:

$('img.example').load(function() {
  $('#spinner').fadeOut();
});

Ver: http://api.jquery.com/load-event/

Use o poder da função setTimeout() (Mais informações) - permite definir um cronômetro para acionar uma chamada de função no futuro e chamá-la não vai bloquear a execução das funções atuais/outras (assíncronas).

Posicione um div contendo o controle giratório acima da imagem do gráfico, com seu atributo de exibição css definido como nenhum:

<div>&nbsp;<img src="spinner.gif" id="spinnerImg" style="display: none;" /></div>

O nbsp impede o colapso do div quando o controle giratório está oculto.Sem ele, quando você alterna a exibição do controle giratório, seu layout irá "se contorcer"

function chartOnClick() {
  //How long to show the spinner for in ms (eg 3 seconds)
  var spinnerShowTime = 3000

  //Show the spinner
  document.getElementById('spinnerImg').style.display = "";

  //Change the chart src
  document.getElementById('chart').src = '/charts/10.png';

  //Set the timeout on the spinner
  setTimeout("hideSpinner()", spinnerShowTime);
}

function hideSpinner() {
  document.getElementById('spinnerImg').style.display = "none";
}

Use CSS para definir a animação de carregamento como uma imagem de fundo centralizada para o contêiner da imagem.

Então, ao carregar a nova imagem grande, primeiro defina o src como um gif transparente pré-carregado de 1 pixel.

por exemplo.

document.getElementById('mainimg').src = '/images/1pix.gif';
document.getElementById('mainimg').src = '/images/large_image.jpg';

Enquanto large_image.jpg está carregando, o fundo será exibido através do gif transparente de 1pix.

Com base na resposta de Ed, prefiro ver algo como:

function PreLoadImage( srcURL, callback, errorCallback ) {
     var thePic = new Image();

     thePic.onload = function() {
          callback();
          thePic.onload = function(){};
     }

     thePic.onerror = function() {
          errorCallback();
     }
     thePic.src = srcURL;
}

Seu retorno de chamada pode exibir a imagem em seu devido lugar e descartar/ocultar um botão giratório, e o errorCallback evita que sua página seja "beachball".Tudo orientado a eventos, sem temporizadores ou pesquisas, além de você não precisar adicionar instruções if adicionais para verificar se o carregamento da imagem foi concluído enquanto você configura seus eventos - como eles são configurados de antemão, eles serão acionados independentemente de como rapidamente as imagens carregam.

Há algum tempo eu escrevi um plugin jQuery que exibe um spinner automaticamente http://denysonique.github.com/imgPreload/

Examinar seu código-fonte deve ajudá-lo a detectar quando exibir o controle giratório e exibi-lo no centro da imagem carregada.

Gosto do método jquery do @duddle, mas acho que load() nem sempre é chamado (como quando a imagem é recuperada do cache no IE).Eu uso esta versão em vez disso:

$('img.example').one('load', function() {
  $('#spinner').remove();
}).each(function() {
  if(this.complete) {
    $(this).trigger('load');
  }
});

Isso chama load no máximo uma vez e imediatamente se já tiver concluído o carregamento.

coloque o spinner em uma div do mesmo tamanho do gráfico, você sabe a altura e a largura para poder usar o posicionamento relativo para centralizá-lo corretamente.

Além da opção lowsrc, também usei um background-image no imgdo contêiner.

Esteja ciente de que a função de retorno de chamada também é chamada se o src da imagem não existir (erro http 404).Para evitar isso você pode verificar a largura da imagem, como:

if(this.width == 0) return false;

A solução da @iAn parece boa para mim.A única coisa que eu mudaria é, em vez de usar setTimeout, tentaria me conectar ao evento 'Load' das imagens.Dessa forma, se o download da imagem demorar mais de 3 segundos, você ainda receberá o botão giratório.

Por outro lado, se o download demorar menos, você obterá o botão giratório por menos de 3 segundos.

Eu adicionaria alguns dígitos aleatórios para evitar o cache do navegador.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top