jQuery Ajax加载带有图像的HTML内容,如何检查所有图像是否已加载?

5
我正在为我的网站编写无限滚动脚本:
$(window).scroll(function(){
  if($(window).scrollTop() == $(document).height() - $(window).height()){
    ...
    $.ajax({
      ...
      success: function(json) {if(json.success){
        ...
        // here I append an Ajax @response with a new element to my existing HTML
        $("#mindIndexSummaryFirst").append(json.items1);
        $("#mindIndexSummarySecond").append(json.items2);
        $("#mindIndexSummaryThird").append(json.items3);
        // here I try to check whether all images are loaded
        $("#mindIndexSummary img").on('load', function(){
          // and I need to call two functions on loaded element
          // hoverImg() need the loaded image to calculate the height
          $('.pi-hover-img'+json.course).hoverImg();
          $(".popup3").tooltip();
        });
      }
    ...
  });

一个已经加载的HTML元素是这样的:
<div class="page-item pi-hover-img  pi-normal">
  <a class="overlayPop" href="#">
  <a class="item_uri" id="course153" href="#">
    <img src="/public/file/course/image/153-course.png" class="pi-item-image">
  </a>
  <a href="#" class="popup5 hide-text" style="display: none;">
    <img src="/public/file/account/image/282-user.jpeg" class="item_image">
  </a>
  <a class="popup action-button big_interested " id="course_153" href="javascript:;" style="top: -162.5px; left: 83.5px; display: none;"> Mi interessa</a>
  <a href="javascript:;">Description</a>
  <a class="popup4 hide-text" href="javascript:;">Preview</a>
  <span class="popup2" style="display: none;">1€</span>
  <a href="/course/153/gestire-un-pubblico">
    <h2 style="top: 320px;">Gestire un pubblico</h2>
    <span class="rfloat pi-icon">
      <img src="/public/img/site_icon/video_course_black.png">
    </span>
    <div class="clearfix"></div>
  </a>
</div>

我加载了5个元素,15张图片,但有可能加载的元素会少一些。

问题是我的函数被调用了多次(我用alert测试了),而我不确定该函数是否在图像加载后被调用。

如果有人遇到过同样的情况,请给我建议。(PS:对于我的糟糕英语,我感到抱歉。)


你的on-load事件处理程序不起作用了吗? - Halcyon
1
每次加载图像(总共 $("#mindIndexSummary img").length 次),都会触发 load 事件。 - Anoop
4个回答

6
$("#mindIndexSummary img").on('load', function(){ });

将处理程序附加到与查询匹配的每个图像上-因此每个图像在加载时都会触发该函数-而不是在所有图像完成加载后仅触发一次。

为了判断它们是否全部加载完毕,您必须跟踪已加载的图像。

大致如下:

var noOfImages = $("#mindIndexSummary img").length;
var noLoaded = 0;

$("#mindIndexSummary img").on('load', function(){ 

    noLoaded++;
    if(noOfImages === noLoaded) {
        handleAllLoaded();
    }

});

非常感谢 :) 我通过对您的代码进行一些更改解决了问题: 当我加载新元素时,我会在其中放入另一个id $('.pi-hover-img'+json.course) "json.course",这会在任何新加载的元素上进行更改。实际上,如果我检查所有图像$("#mindIndexSummary img").length; 我有许多先前加载的图像。但是我需要新加载的图像数量,我可以使用我添加的id获取此数字:var noOfImages = $('.pi-hover-img'+json.course+" img").length; - Artur Mamedov

0
这是我在类似情况下使用的解决方案的草稿版本。每次执行load方法时,都会更新numLoaded,这使您可以检查预测值(numImage)是否等于已加载的图像总数。
var img =  $( '#mindIndexSummary' ).find( 'img' )
  , numImage = img.length;

img.on( 'load', function(){

    var self = $( this )
      , numLoaded  = self.attr( 'data-loaded', true ).length;

    self.attr( 'data-loaded', true );

    if( numImages === numLoaded ) 

    funcToCall();   


});

此外,您还可以更进一步,在父元素上设置一个data属性,这将允许您根据其值触发/终止其他事件。
var parent = $( '#mindIndexSummary' )
  , img =  $( '#mindIndexSummary' ).find( 'img' )
  , numImage = img.length;

img.on( 'load', function(){

    var self = $( this )
      , numLoaded  = self.attr( 'data-loaded', true ).length;

    parent.attr( 'data-load', 'loading' );
    self.attr( 'data-loaded', true );

    if( numImages === numLoaded ) 

    parent.attr( 'data-load', 'complete' );
    funcToCall();   


});

if( parent.attr('data-load').slice( 0, 7 ) === 'loading' )
do something else

0

图片的加载事件有点不可靠(请参阅Jquery文档http://api.jquery.com/load-event/)。 尽管如此,可以通过逐个检查每个选定图像上的加载事件来组装解决方案。很有可能在执行时图像已被缓存或已加载。在这种情况下,图像元素应具有“.complete”属性。

我制作了一个小型的jQuery插件来说明这种方法(无论如何都有更完整的插件):

(function($) {
    $.fn.imagesLoaded = function(options) {
        var images = this.find("img"), 
            loadedImages = [], 
            options = options;

        images.each(function(i, image) {
            function loaded() {
                loadedImages.push(this);
                if(options.imageLoaded) {
                    options.imageLoaded(this);    
                }
                if(loadedImages.length == images.length) {
                    if(options.complete) {
                        options.complete(loadedImages);    
                    }
                }
            }

            if(image.complete || image.complete === undefined) {
                // Image is already loaded
                loaded.call(image);               
            } else {
                // Image is not loaded yet, bind event
                $(image).load(loaded);
            }
        });
    }
})(jQuery);

该插件接受一个哈希值,其中包含两个回调函数,一个在每次加载图像时触发(图像作为参数传递),另一个在所有图像加载完成时触发(图像数组作为参数传递)。

$("#element-containing-images").imagesLoaded({
    imageLoaded: function(image) {
       console.log("Image loaded:", image); 
    }, 
    complete: function(images) {
        console.log("All images loaded:", images);
    }
});

这并不是完整的,存在一些小问题,但它应该可以给你一个大致的想法。 我在http://jsfiddle.net/GYJGK/上提供了一个小演示。


0
这是一个关于如何创建全局变量(数组),以跟踪加载的每个单独图像的描述。这样,您可以使用回调函数主动检查所有图像何时加载完成。
var image_state_array = new Array(false, false, false, false, false, false, false, false, false, false);

数组中的每个位置都将跟踪已加载的图像。例如,如果在10张图片列表中加载了第2张图片,则数组将如下所示(请记住,数组索引从0开始):

var image_state_array = new Array(false, false, true, false, false, false, false, false, false, false);

假设你有一个图像列表,根据某些用户交互(例如用户点击刷新以获取新的可供选择的图像集)进行动态重新加载。一旦所有图像都已加载完毕,您希望向用户发出已加载完毕的提示(或调用其他类型的函数)。首先为即将加载的图像设置onload事件。
//get image 0

var image = document.getElementsByClassName("search_images")[0];

//track the image load state 

image.onload = function(){
      trackImageLoadState(0); //note that 0 is the image index from the list of elements 
}

接下来像往常一样设置图像的来源。这将触发onload事件并调用该函数。

//set the source of the image, 

    image.src = desireImagePNG;

轨道图像加载状态将添加已加载的图像到image_state_array中,跟踪image0已加载。记录image0已加载后,它会循环遍历image_state_array并计算返回的已加载图像数量。如果已加载足够的图像,则执行您尝试实现的任何功能。在此示例中,我正在淡出加载屏幕。
    function trackImageLoadState(numImage){
      //debug print
      //console.log("numImage: " + numImage);

      //set the array image value to true of the passed in index 
      image_state_array[numImage] = true;

      //debug print
      //console.log("image_state_array[numImage] " + image_state_array[numImage] );

      var loadedImagesCount = 0;

      //loop through the array and count the amount of images that have loaded
      for(var counter2 = 0; counter2 < image_state_array.length; counter2++){
        //debug print
        //console.log("image_state_array[counter] " + image_state_array[counter2] + "counter" + counter2 );

        if(image_state_array[counter2]){
          loadedImagesCount++;
        }
      }

      //debug print
      //console.log("loadedImagesCount: " + loadedImagesCount);

      //if the amount of images required to be loaded has been met, execute function. If you want to know when all images have been loaded, you need to set the if statement condition to the total count of images. For example:
if(loadedImagesCount>10){} if you have 10 images. 

  if(loadedImagesCount>5){

    //fade out the loading screen - any other function will work here as well
    fadeOutMainLoadingScreen();

  }

}

请记住,每次调用操作时,全局变量都必须被重置。可以按照以下方式完成:
//reset the global variable array to track the new load of images 

for(var i = 0; i < image_state_array.length; i++){
  image_state_array[i] = false;
}

这是一种通过回调函数和全局变量追踪已加载的图像的有效方法。请评论,因为我知道它可能需要改进和更加动态化。谢谢!


谢谢,但在我的情况下,我更喜欢使用jQuery或其他可以跟踪整个加载过程的东西,因为我无法知道或需要做些什么来了解我需要加载多少张图片。 - Artur Mamedov

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