Как я могу проверить, загружено ли фоновое изображение?

154

Я хочу установить фоновое изображение для тега body, а затем запустить некоторый код, например так:

$('body').css('background-image','http://picture.de/image.png').load(function() {
    alert('Background image done loading');
    // This doesn't work
});

Как я могу убедиться, что фоновое изображение полностью загружено?

Питер
источник
4
Просто назначьте тот же URL для Image()объекта, который имеет onloadсобытие.
Shadow Wizard - это ухо для тебя
2
убедитесь, что оберните CSS-URL вurl()
bluescrubbie

Ответы:

275

попробуй это:

$('<img/>').attr('src', 'http://picture.de/image.png').on('load', function() {
   $(this).remove(); // prevent memory leaks as @benweet suggested
   $('body').css('background-image', 'url(http://picture.de/image.png)');
});

это создаст новое изображение в памяти и будет использовать событие load для определения момента загрузки src.

jcubic
источник
10
Похоже, что изображение будет загружено дважды без причины.
HyderA
49
@gAMBOOKa Они загружаются один раз, потому что они остаются в памяти браузера. Это то же самое, когда вы кладете скрытые изображения в верхней части своей страницы, а затем устанавливаете его в CSS - чтобы изображения начинали загружаться до файла CSS - это называется предварительной загрузкой.
jcubic
4
Я не слишком уверен, но я думаю, что вы имеете в виду кэш. Я не думаю, что есть такая вещь, как память браузера, где хранятся активы. Если вы имеете в виду кэш, помните, что вы добавляете дополнительный HTTP-запрос, и на всех клиентах может быть не включен кэш.
HyderA
7
Введите это на любой странице, где есть jquery: javascript:void($('<img/>').attr('src', 'http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg').load(function() { $('html').css('background-image', 'url(http://farm6.static.flickr.com/5049/5220175127_5693faf952.jpg)'); }))и проверьте HTTP-запросы в Firebug. Если я открыл страницу мерцания с этим изображением, открытым на другой вкладке, он не выполняет никаких HTTP-запросов, просто показывает эту картинку мгновенно. и когда я очищаю кеш и запускаю его, был один запрос.
jcubic
26
Сравнение этого теста и это одно показывает , что вы должны вызвать .remove()на $('<img/>')объект , чтобы избежать утечек памяти. Вы должны увидеть стабильное потребление памяти в первом тесте и увеличение памяти во втором. После нескольких часов работы на Chrome 28 первый тест занимает 80 МБ, а второй - 270 МБ.
Бенвит
23

У меня есть JQuery плагин называется , waitForImagesкоторый может обнаружить , когда фоновые изображения загрузили.

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);
Алекс
источник
Этот плагин также отлично подходит для возможности показать прогресс загрузки с помощью eachобратного вызова.
Совют
1
@alex, как проверить каждое фоновое изображение для каждого элемента в классе? Я попробовал это, но, кажется, не делает это правильно. $ ('. user_main_photo_thumb'). waitForImages (function () {$ (this) .parents ('. photoThumbFrame'). delay (1000) .slideDown ();}, функция (загружена, считать, успешна) {});
Relm
@Relm Вы не используете это правильно. Второй обратный вызов для каждого изображения. Кроме того, delay()не работает так.
Алекс
16

Что-то вроде этого:

var $div = $('div'),
  bg = $div.css('background-image');
  if (bg) {
    var src = bg.replace(/(^url\()|(\)$|[\"\'])/g, ''),
      $img = $('<img>').attr('src', src).on('load', function() {
        // do something, maybe:
        $div.fadeIn();
      });
  }
});
Colin
источник
привет ... это похоже на работу, хотя я установил для bg.replace значение bg.replace( ... , my_src ). Но мой вопрос: как только $ ('<img>') загружается, что именно происходит с этим <img>... Я имею в виду, что это на самом деле не реально - это просто фиктивный заполнитель, верно?
dsdsdsdsd
Правильно. <img>Никогда не вставляется в DOM; он просто используется, чтобы «обмануть» браузер при загрузке файла изображения в кеш.
Колин
полезно, если вы не хотите вызывать jQuery
vwvan
15

Для CSS-ресурсов нет обратных вызовов JS.

Адриан Пакала
источник
3
Спасибо за быстрый ответ. Есть идеи для обходного решения?
Питер
но есть решение JS для тех, кто ищет stackoverflow.com/questions/5057990/…
godblessstrawberry
8

Чистое решение JS, которое добавит preloader, установит background-image и затем настроит его для сборки мусора вместе со слушателем событий :

Укороченная версия:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector("body");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
    bgElement.style.backgroundImage = `url(${imageUrl})`;
    preloaderImg = null;
});

Немного дольше с хорошим переходом непрозрачности:

const imageUrl = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
let bgElement = document.querySelector(".bg-lazy");
bgElement.classList.add("bg-loading");
let preloaderImg = document.createElement("img");
preloaderImg.src = imageUrl;

preloaderImg.addEventListener('load', (event) => {
  bgElement.classList.remove("bg-loading");
  bgElement.style.backgroundImage = `url(${imageUrl})`;
  preloaderImg = null;
});
.bg-lazy {
  height: 100vh;
  width: 100vw;
  transition: opacity 1s ease-out;
}

.bg-loading {
  opacity: 0;
}
<div class="bg-lazy"></div>

godblessstrawberry
источник
3
Недооцененное решение.
Том Томсон
1
@TomThomson спасибо, Том, я обнаружил, что переход изображений не работает должным образом, исправил это
godblessstrawberry
6

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

Прочитать статью:

http://catmull.uk/code-lab/background-image-loaded/

или перейдите прямо к коду плагина:

http://catmull.uk/downloads/bg-loaded/bg-loaded.js

Так что просто включите плагин и затем вызовите его на элементе:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded();
</script>

Очевидно, скачать плагин и хранить его на своем собственном хостинге.

По умолчанию он добавляет дополнительный класс «bg -loaded» к каждому сопоставленному элементу после загрузки фона, но вы можете легко изменить это, передав ему другую функцию, подобную этой:

<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
   $('body').bgLoaded({
      afterLoaded : function() {
         alert('Background image done loading');
      }
   });
</script>

Вот кодекс, демонстрирующий его работу.

http://codepen.io/catmull/pen/Lfcpb

Джон Кэтмалл
источник
3

Я нашел решение, которое работало лучше для меня, и которое имеет преимущество в том, что его можно использовать с несколькими изображениями (случай не показан в этом примере).

Из ответа @ adeneo на этот вопрос :

Если у вас есть элемент с фоновым изображением, как это

<div id="test" style="background-image: url(link/to/image.png)"><div>

Вы можете дождаться загрузки фона, получив URL-адрес изображения и используя его для объекта изображения в javascript с обработчиком загрузки.

var src = $('#test').css('background-image');
var url = src.match(/\((.*?)\)/)[1].replace(/('|")/g,'');

var img = new Image();
img.onload = function() {
    alert('image loaded');
}
img.src = url;
if (img.complete) img.onload();
Paperjuice
источник
2

Я сделал чистый взлом JavaScript, чтобы сделать это возможным.

<div class="my_background_image" style="background-image: url(broken-image.jpg)">
<img class="image_error" src="broken-image.jpg" onerror="this.parentElement.style.display='none';">
</div>

Или

onerror="this.parentElement.backgroundImage = "url('image_placeHolder.png')";

CSS:

.image_error {
    display: none;
}
Джино
источник