如何在使用JavaScript加载图像时显示旋转符号。

57

我目前正在开发一个网页应用程序,其中有一个页面显示单个图表(.png 图像)。在此页面的另一部分中有一组链接,当点击时,整个页面会重新加载,并且与之前完全相同,除了页面中间的图表。

我想要做的是,在单击链接时只更改页面上的图表。这将极大地加快速度,因为页面大约有 100kb 的大小,不希望重新加载整个页面来显示它。

我一直在使用 JavaScript 来实现这一点,到目前为止效果还不错,使用以下代码:

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

问题在于当用户点击链接后,图表可能需要几秒钟才能更改。这会让用户认为他们的点击没有起作用,或者系统响应速度很慢。

我希望发生的事情是,在加载图片时,在图片位置上显示一个旋转图标/状态指示器,这样当用户单击链接时,他们至少知道系统已接受了他们的输入并正在采取措施。

我尝试过一些建议,甚至使用伪超时来显示旋转图标,然后再切换回图片。

我收到的一个好建议是使用以下方法:

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

除了显示的图表比微调器要大之外,微调器确实是最理想的选择。

还有其他的想法吗?


1
对于桌面用户,您还可以更改光标以显示某些操作正在进行。您需要使用一些CSS,例如body.waiting{cursor: wait;},然后使用JavaScript切换它:document.body.classList.add('waiting');,并在图像加载时使用:document.body.classList.remove('waiting'); - Yeti
13个回答

41

我之前用过类似的东西来预加载一张图片,并在图片加载完成后自动回调我的 JavaScript。在设置回调之前,你需要检查是否已经加载完全,因为图片可能已经被缓存,这样它就可能不会调用你的回调函数。

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(){};
    }
  }
}

19

12

使用 jQueryload() 方法,可以轻松地在图片加载完成时执行某些操作:

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

参见:http://api.jquery.com/load-event/


1
使用 load 的方式已经被弃用(在3.0中已删除),并已被加载事件所取代。 - Liam

10

利用setTimeout()函数的威力(更多信息)-这允许您设置一个计时器,在未来触发函数调用,并且调用它不会阻塞当前/其他函数的执行(异步)。

将包含spinner的div定位在图表图像上方,将其css显示属性设置为none:

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

当旋转图标隐藏时, 可以使用  stop  来防止 div 元素折叠。如果没有它,在切换旋转图标的显示时,会导致页面布局抖动。


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";
}

4
setTimeout函数不需要将第一个参数用引号括起来 - 你可以这样调用它:setTimeout(hideSpinner, spinnerShowTime);这样可以避免JS解释器对字符串进行评估,减少了开销。 - Jason Bunting
在这种情况下,这样做可能更快,但如果您想要向函数传递参数,我发现将内容括在双引号中会导致较少的问题(我想这是以可读性为代价的)。 - Ian
@iAn,你在回答中添加的链接已经失效了。 - Adriano

4
使用CSS将加载动画设置为图像容器的居中背景图像。 在加载新的大型图像时,首先将src设置为预加载的透明1像素gif。
例如: document.getElementById ('mainimg').src ='/ images / 1pix.gif'; document.getElementById ('mainimg').src ='/ images / large_image.jpg';
当加载large_image.jpg时,背景将透过1像素透明gif显示出来。

3

我喜欢@duddle的jQuery方法,但发现在IE中从缓存中检索图像时并不总是调用load()。相反,我使用以下版本:

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

这个调用最多只加载一次,如果已经完成加载,则立即执行。

1
应该使用 .on() 而不是 .one()。 - AO_
4
不,你误解了。在这种情况下,我只想触发一次加载。http://api.jquery.com/one/ - BC.

3

在Ed的回答基础上,我更倾向于看到以下内容:

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

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

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

您的回调函数可以将图像显示在其正确位置并处理/隐藏旋转器,而errorCallback可以防止页面“卡住”。所有事件驱动,没有定时器或轮询,而且您不必添加额外的if语句来检查图像是否在设置事件时完成加载 - 因为它们是预先设置的,所以无论图像加载速度有多快,它们都会触发。


3

之前,我写了一个jQuery插件,自动处理显示加载图标的问题。源代码在这里:http://denysonique.github.com/imgPreload/

查看源代码能帮助你检测何时应该显示加载图标,并将其显示在已加载图像的中心位置。


1

请注意,如果图片的 src 不存在(http 404 错误),回调函数也会被调用。为避免这种情况,您可以检查图片的宽度,例如:

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

1
将旋转器放置在一个与图表相同大小的 div 中,您知道高度和宽度,所以可以使用相对定位来正确地居中它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接