代码之家  ›  专栏  ›  技术社区  ›  dclowd9901

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

  •  3
  • dclowd9901  · 技术社区  · 14 年前

    我正在尝试编写一个插件,它有一个内置函数,可以等到页面上的所有图像都被加载后再执行。 $(window).load() 只有当它是页面的初始加载时才起作用,但是如果有人想通过包含图像的AJAX下拉一些HTML,它就不起作用了。

    有什么好的方法可以做到这一点并实现它,这样它就可以在插件中自包含了吗?我试过绕过去 $('img').complete ,我知道这不起作用(图像永远不会加载,浏览器在“脚本花费太长时间才能完成”的错误下崩溃)。举一个我想做的例子,请访问我要放置插件的页面:

    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 回复  |  直到 14 年前
        1
  •  3
  •   noah    14 年前

    图像循环和调用的问题 $('img').complete 浏览器用户界面是单线程的,所以你永远不会给它加载图像的机会,因为它总是在你的循环中。你可以用 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
  •  3
  •   naugtur    14 年前

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

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

    或者当你期待大量图片时:

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

    如果上面的任何代码都不能正常工作,您可能希望将代码放入回调中,在添加html后将其添加到站点。在上面的函数中使用setTimeout也会有所帮助。

    [编辑]

    您可以生成图像 <img src="something" onload="$.imgHello()" /> $.imgHello() 函数调用,如果你知道有多少图像将被加载。但这不是我推荐给任何人的解决方案。

        3
  •  2
  •   dclowd9901    14 年前

    在尝试以几乎所有可以想象的方式完成这项任务之后,这一次终于奏效了,非常感谢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() 基本上可以作为任何你想等待执行的函数,直到所有的图像都被加载(在我的例子中,它是整个插件)。图德尔。

        4
  •  1
  •   Andy E    14 年前

    你想过用 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 */
    });