jQuery:动态图像处理(等待加载)

时间:2010-03-30 15:13:41

标签: jquery image load callback

我正在尝试编写一个内置函数的插件,等待页面上的所有图像在执行之前加载。 $(window).load()仅在页面的初始加载时才有效,但如果有人想通过包含图像的AJAX下载某些HTML,则它不起作用。

有没有好的方法来实现它并实现它,以便它可以在插件中自包含?我试过循环$('img').complete,我知道这不起作用(图像永远不会加载,浏览器崩溃,“脚本需要很长时间才能完成”bug)。有关我正在尝试执行的操作的示例,请访问我要查找的插件页面:

http://www.simplesli.de

如果您转到“更多用途”部分(在导航栏上单击它),您将看到图像幻灯片显示无法正确加载。我知道当前的代码不起作用,但只是在我解决问题之前就一直存在。

编辑:尝试此解决方案,但它不起作用:

if($('.simpleSlide-slide img').size() > 0) {
    var loaded_materials = $('.simpleSlide-slide img').get();
} else {
    var loaded_materials = $('.simpleSlide-slide').get();
}

$(loaded_materials).live('load', function() {
         /* Image processing and loading code */
    });

4 个答案:

答案 0 :(得分:3)

我认为你需要将一个函数绑定到全局ajaxSuccess,然后将一个load事件绑定到页面上的每个图像。

$.ajaxSuccess(function(){
 $('img').load(function(){
  //Your code here
 });
});

或当您期待大量图片时:

$.ajaxSuccess(function(){
 $('img:not(.loaded)').addClass('.loaded').bind('load',function(){
  //Your code here
 });
});

如果以上代码中的任何一个代码无法正常工作,那么Tou可能希望将代码放入一个回调中,在添加后将html添加到网站。在上面的函数中使用setTimeout也可能有所帮助。

[编辑]

如果你知道要加载多少个图像,你可以在服务器端代码中生成图像<img src="something" onload="$.imgHello()" />并在每个$.imgHello()函数调用中递增一些计数器。但这不是我向任何人推荐的解决方案。

答案 1 :(得分:3)

循环遍历图像并调用$('img').complete的问题是浏览器UI是单线程的,所以你永远不会给它加载图像的机会,因为它总是在你的循环中。您可以使用setTimeout来允许浏览器工作。如,

$.get("whatever",function(html) {
   $('#foo').html(html);
   var images = getTheImages();
   function checkImages() {
      var done = true;
      $.each(images,function() {
         done = done && this.complete;
         return done;
      });
      if(done) {
        fireEvent();
      } else {
        setTimeout(checkImages,100); // wait at least 100 ms and check again
      }
   }
});

答案 2 :(得分:1)

您是否考虑过使用live()绑定所有当前和未来的img元素?

$('img').live('load', function ()
{
    alert("image loaded: "+this.src);
});

更新后,我可以看到您遇到的问题。 live()最适合选择器,而你在jQuery包装的元素数组上使用它。像这样使用live()与使用bind()没有什么不同。你应该尝试这样的事情:

if($('.simpleSlide-slide img').size() > 0) {
    var loaded_materials = '.simpleSlide-slide img';
} else {
    var loaded_materials = '.simpleSlide-slide';
}

$(loaded_materials).live('load', function() {
         /* Image processing and loading code */
});

答案 3 :(得分:1)

在尝试以几乎所有可以想象的方式完成这项任务之后,这个是最终工作的那个,并且非常感谢Naugtur指出我正确的方向:

var no_of_images = $('img').size();

$.extend(no_of_images);

if(no_of_images > 0) {

    var images = new Array();
    var i = 0;
    $('img').each( function() {
        images[i] = $(this).attr('src');
        i++;
    });

    i = 0;

    $(images).each( function(){
        var imageObj = new Image();
        imageObj.src = images[i];
        $(imageObj).load( function() {
            no_of_images--;
            i++;
            if(no_of_images == 0){
                functionToPerform();
            }
        });
    });
} else {
    functionToPerform();
}

为了快速解释发生了什么,我会用一个类比。想象一下,每个图像都是您聚会的嘉宾。灯灭了。你翻转灯,然后比赛给每个客人,并给他们一张纸,一支笔和一部手机,同时计算你把材料递给了多少人。他们都开始疯狂地画画,然后他们一完成图纸就打电话给你并告诉你。对于每一个打电话的人,你都会从你的董事会中抽出一个记录。当最后一个人打电话给你时(当你的电路板上的计数标记用完时),你告诉他们挂断并打电话给披萨家伙。这是比萨时间。如果没有客人开始,你自己打电话给披萨店。

如果您正在考虑“为什么他为每个Image()创建一个$.load()对象,那么,我尝试使用传统的jQuery路由,使用直接的jQuery样式选择器而不是图像对象它似乎完全被忽略了(这使页面崩溃了。)我尝试将Image().onLoad结合使用,并且只要不崩溃页面就可以工作,但它没有执行其中的功能我写了。

这段代码是自包含的,所以我想它可以被复制到任何图像加载应用程序中。这对我来说似乎足够小,以免侵入。 functionToPerform()基本上充当您想要等待执行的任何函数,直到加载所有图像(在我的情况下,它是整个插件)。 Toodles。