jQuery: динамическая обработка изображений (ожидание загрузки) - PullRequest
3 голосов
/ 30 марта 2010

Я пытаюсь написать плагин, который имеет встроенную функцию, чтобы дождаться загрузки всех изображений на странице, прежде чем он запустится сам.$(window).load() работает только в том случае, если это начальная загрузка страницы, но если кто-то хочет получить доступ к HTML через AJAX, содержащий изображения, он не работает.

Есть ли хороший способ сделать этореализовать его, чтобы он мог быть автономным в плагине?Я пробовал зацикливаться на $('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 ]

3 голосов
/ 31 марта 2010

Проблема с зацикливанием изображений и вызовом $('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
      }
   }
});
3 голосов
/ 30 марта 2010

Я думаю, вам нужно привязать функцию к глобальному 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(), если Вы знаете, сколько изображений там будет загружено. Но это не решение, которое я бы рекомендовал никому.

1 голос
/ 31 марта 2010

После попытки выполнить эту задачу практически всеми возможными способами именно этот наконец-то сработал, и большое спасибо 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 вместо объекта Object. Казалось бы, полностью игнорируется (что приводит к сбою страницы). Я пытался использовать Image() в сочетании с .onLoad, и это работало, поскольку не срывало страницу, но не выполняло функцию, для которой я ее написал.

Этот фрагмент кода является автономным, поэтому я думаю, что его можно скопировать в любое приложение для загрузки изображений. Это кажется мне достаточно маленьким, чтобы не быть навязчивым. functionToPerform() в основном действует как любая функция, которую вы хотели бы подождать, пока не загрузятся все изображения (в моем случае это был весь плагин). Toodles.

1 голос
/ 30 марта 2010

Задумывались ли вы об использовании 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 */
});
...