Независимый от браузера способ определить, когда изображение было загружено - PullRequest
55 голосов
/ 04 мая 2009

В IE вы можете onreadystatechange. Есть нагрузка, но я читаю страшные вещи . jQuery довольно хорошо завершает событие загрузки DOM с помощью команды «ready». Кажется вероятным, что я просто не осведомлен о реализации загрузки изображений в другой хорошей библиотеке.

Контекст заключается в том, что я генерирую изображения динамически (с помощью обратных вызовов сервера), загрузка которых может занять некоторое время. В моем коде, предназначенном только для IE, я установил src элемента img, а затем, когда событие onreadystatechange срабатывает со статусом «complete», я добавляю его в DOM, чтобы пользователь его увидел.

Я был бы доволен "нативным" решением JavaScript или указателем на библиотеку, которая выполняет эту работу. Там так много библиотек, и я уверен, что это тот случай, когда я просто не знаю о правильной. Тем не менее, мы уже являемся пользователями jQuery, поэтому я не собираюсь добавлять очень большую библиотеку только для того, чтобы получить эту функциональность.

Ответы [ 9 ]

47 голосов
/ 10 июня 2010

ПРИМЕЧАНИЕ: Я написал это в 2010 году, браузерами в дикой природе были IE 8/9 beta, Firefox 3.x и Chrome 4.x. Пожалуйста, используйте это только для исследовательских целей, я сомневаюсь, что вы можете скопировать / вставить это в современный браузер и заставить его работать без проблем.

ПРЕДУПРЕЖДЕНИЕ: Сейчас 2017 год, я все еще получаю очки по этому вопросу время от времени, пожалуйста, используйте это только в исследовательских целях. В настоящее время я понятия не имею, как определить состояние загрузки изображения, но, вероятно, есть гораздо более изящные способы сделать это, чем это ... по крайней мере, я серьезно надеюсь, что есть. Я настоятельно рекомендую НЕ использовать мой код в производственной среде без дополнительных исследований.


Я немного опоздал на эту вечеринку, может быть, этот ответ поможет кому-то еще ...

Если вы используете jQuery, не беспокойтесь о обработчиках стандартных событий (onclick / onmouseover / etc), фактически просто прекратите их использование. Используйте методы событий, которые они предоставили в своем API .


Это предупредит, прежде чем изображение будет добавлено к телу, потому что событие загрузки запускается, когда изображение загружается в память. Он делает именно то, что вам говорят: создайте изображение с помощью теста test.jpg, когда test.jpg загрузит предупреждение, затем добавьте его к телу.

var img = $('<img src="test.jpg" />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);

Это предупредит после вставки изображения в тело, снова делая то, что вы ему сказали: создайте изображение, установите событие (src не установлено, поэтому оно не загружено), добавьте изображение к body (все еще нет src), теперь установите src ... теперь изображение загружено, поэтому событие инициируется.

var img = $('<img />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);
$img.attr('src','test.jpg');

Конечно, вы также можете добавить обработчик ошибок и объединить несколько событий, используя bind ().

var img = $('<img />');
img.bind({
    load: function() {
        alert('Image loaded.');
    },
    error: function() {
        alert('Error thrown, image didn\'t load, probably a 404.');
    }
});
$('body').append(img);
img.attr('src','test.jpg');

По запросу @ChrisKempen ...

Вот не управляемый событиями способ определения, не повреждены ли изображения после загрузки DOM. Этот код является производным кода от статьи StereoChrome , которая использует атрибуты naturalWidth, naturalHeight и complete, чтобы определить, существует ли изображение.

$('img').each(function() {
    if (this.naturalWidth === 0 || this.naturalHeight === 0 || this.complete === false) {
        alert('broken image');
    }
});
11 голосов
/ 04 мая 2009

В соответствии со спецификацией W3C , только элементы BODY и FRAMESET предоставляют событие «onload» для подключения. Некоторые браузеры поддерживают его независимо, но имейте в виду, что для реализации спецификации W3C не требуется.

Что-то, что может иметь отношение к этому обсуждению, хотя это не обязательно ответ, в котором вы нуждаетесь, это обсуждение:

Событие Image.onload не запускается в Internet Explorer, когда изображение находится в кеше


Что-то еще, что может быть связано с вашими потребностями, хотя может и не быть, это информация о поддержке синтезированного события "onload" для любого динамически загружаемого элемента DOM:

Как определить, был ли динамически созданный элемент DOM добавлен в DOM?

5 голосов
/ 04 мая 2009

Единственный надежный способ, который я нашел, - это делать все на стороне клиента, как это ...

var img = new Image();
img.onload = function() {
  alert('Done!');
}
img.src = '/images/myImage.jpg';
3 голосов
/ 12 мая 2009

Хорошо, я постараюсь обобщить различные частичные ответы здесь (включая мой).

Казалось бы, ответ заключается в использовании onload, который "широко поддерживается", хотя официально не требуется в соответствии со стандартами. Обратите внимание, что для IE, в частности, вы должны установить onLoad перед установкой атрибута src, иначе он может не запускаться при загрузке изображения из кэша. В любом случае это кажется наилучшей практикой: настройте обработчики событий перед тем, как начинать запуск событий. Там, где onload не поддерживается, следует предположить, что функциональность просто недоступна.

3 голосов
/ 04 мая 2009

Я думаю onload должно работать нормально. Вам нужно сгенерировать разметку для изображений, или вы можете добавить их статически? Если последнее, я бы предложил следующее:

<img src="foo.png" class="classNeededToHideImage" onload="makeVisible(this)">

В качестве альтернативы, вы можете использовать window.onload, чтобы сделать все изображения видимыми одновременно - window.onload срабатывает после завершения загрузки всех внешних ресурсов.

Если вы хотите добавить изображения динамически, сначала нужно дождаться, пока DOM будет готов к изменению, то есть использовать jQuery или реализовать собственный взлом DOMContentLoaded для браузеров, которые не поддерживают его изначально.

Затем вы создаете объекты изображений, назначаете onload слушателей, чтобы сделать их видимыми, и / или добавляете их в документ.

Еще лучше (но немного сложнее) было бы создать и начать загружать изображения сразу после запуска скрипта. В DOMContentLoaded вам нужно проверить каждое изображение на complete, чтобы решить, добавлять ли их немедленно в документ или подождать, пока обработчик изображения onload не сработает.

1 голос
/ 04 июня 2012

HTML

<img id="myimage" src="http://farm4.static.flickr.com/3106/2819995451_23db3f25fe_t.jpg"/>​

SCRIPT

setTimeout(function(){
    $('#myimage').attr('src','http://cdn.redmondpie.com/wp-content/uploads/2011/05/canarylogo.png').load(function(){
        alert('Main Image Loaded');

        $('#myimage').attr('src','image.jpg').bind({
            load: function(){
                alert('Image loaded.');
            },
            error: function(){
                alert('Image not loaded.');
            }
        });
    });
},1000);

JS Fiddle

http://jsfiddle.net/gerst20051/sLge3/

1 голос
/ 06 мая 2009

Казалось бы, ответ - использовать onreadystatechange в IE и onLoad в других браузерах. Если ни один не доступен, сделайте что-нибудь еще. onLoad предпочтительнее, но IE не запускает его при загрузке изображения из кэша, как отмечено в одном из ответов ниже

1 голос
/ 04 мая 2009

Если я не ошибаюсь в javascript, тег изображения содержит события onload и onerror

Вот интересный фрагмент кода, который я сделал, чтобы скрыть испорченные изображения

в теге стиля

img.failed{
   display:none;
}

с помощью img onerror, у меня был кусок javascript, который сделал это.className = fail и он будет скрывать изображение, если оно ошибочно

однако я мог неправильно понять, какова ваша цель

0 голосов
/ 02 августа 2017

Использование URI данных - это путь. Однако использование SVG вместо GIF обеспечивает большую гибкость. Вы можете быстро изменить размер. Просто запустите это в консоли JavaScript:

var width = 1;
var height = 1;
'data:image/svg+xml;base64,' +
btoa(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"/>`);

Пример вывода:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxIiBoZWlnaHQ9IjEiLz4=

Я собрал быструю утилиту CodePen для создания прозрачных SVG с произвольными размерами . Он довольно простой, поэтому вам нужно изменить его, если вы хотите добавить цвет или другие функции к изображению.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...