Jak mogę sprawdzić, czy obraz tła jest załadowany?

154

Chcę ustawić obraz tła na tagu body, a następnie uruchomić kod - na przykład:

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

Jak mogę się upewnić, że obraz tła jest w pełni załadowany?

Piotr
źródło
4
Po prostu przypisz ten sam adres URL do Image()obiektu, który ma onloadzdarzenie.
Shadow Wizard is Ear For You
2
pamiętaj, aby url()
umieścić

Odpowiedzi:

274

Spróbuj tego:

$('<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)');
});

stworzy to nowy obraz w pamięci i użyje zdarzenia load do wykrycia, kiedy src jest ładowany.

jcubic
źródło
10
Wygląda na to, że obraz zostałby załadowany dwukrotnie bez powodu.
HyderA
49
@gAMBOOKa Są ładowane raz, ponieważ pozostają w pamięci przeglądarki. Tak samo jest, gdy umieścisz ukryte obrazy u góry strony, a następnie ustawisz je w CSS - więc obrazy są pobierane przed plikiem css - nazywa się to ładowaniem wstępnym.
jcubic
4
Nie jestem pewien, ale myślę, że masz na myśli pamięć podręczną. Nie sądzę, by istniało coś takiego jak pamięć przeglądarki, w której przechowywane są zasoby. Jeśli odnosisz się do pamięci podręcznej, pamiętaj, że dodajesz dodatkowe żądanie HTTP i wszyscy klienci mogą nie mieć włączonej pamięci podręcznej.
HyderA
7
Wpisz to na dowolnej stronie, która zawiera 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)'); }))i sprawdź żądania HTTP w Firebug. Jeśli otworzyłem stronę migotania z tym obrazem otwartym w innej karcie, nie wysyła żadnych żądań HTTP, po prostu natychmiast wyświetla to zdjęcie. a kiedy wyczyściłem pamięć podręczną i uruchomiłem ją, było jedno żądanie.
jcubic
26
Porównanie tego testu i ta, pokazuje, że trzeba zadzwonić .remove()na $('<img/>')obiekt, aby uniknąć wycieku pamięci. Powinieneś zobaczyć stabilne zużycie pamięci w pierwszym teście i wzrost pamięci w drugim. Po kilku godzinach pracy na Chrome 28 pierwszy test zajmuje 80 MB, a drugi 270 MB.
benweet
23

Mam wtyczkę jQuery o nazwie, waitForImagesktóra może wykryć, kiedy obrazy tła zostały pobrane.

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);
Alex
źródło
Ta wtyczka jest również świetna do wyświetlania postępu ładowania za pomocą eachwywołania zwrotnego.
Soviut,
1
@alex, Jak mam sprawdzić każdy obraz tła dla każdego elementu w klasie? Próbowałem tego, ale nie wydaje się, że robię to dobrze. $ ('. user_main_photo_thumb'). waitForImages (function () {$ (this) .parents ('. photoThumbFrame'). delay (1000) .slideDown ();}, function (load, count, success) {});
Relm
@Relm Nie używasz go poprawnie. Drugie wywołanie zwrotne dotyczy obrazu. Poza tym delay()tak nie działa.
Alex
16

Coś takiego:

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
źródło
cześć ... wydaje się, że działa, chociaż ustawiłem bg.replace na bg.replace( ... , my_src ). Ale moje pytanie brzmi: po załadowaniu $ ('<img>'), co dokładnie się z tym dzieje <img>... Mam na myśli to, że tak naprawdę nie jest - to tylko fikcyjny symbol zastępczy, prawda?
dsdsdsdsd
Dobrze. <img>Nie jest włożona do DOM; służy tylko do "oszukiwania" przeglądarki, aby załadowała plik obrazu do pamięci podręcznej.
Colin
przydatne, jeśli nie chcesz wywoływać jQuery
vwvan
15

Nie ma wywołań zwrotnych JS dla zasobów CSS.

Adrian Pacala
źródło
3
Dzięki za szybką odpowiedź. Jakieś pomysły na obejście problemu?
Peter,
ale jest rozwiązanie JS dla tych, którzy szukają stackoverflow.com/questions/5057990/ ...
godblessstrawberry
8

czyste rozwiązanie JS, które doda moduł ładowania wstępnego, ustawi obraz tła, a następnie skonfiguruje go pod kątem zbierania elementów bezużytecznych wraz z odbiornikiem zdarzeń :

Krótka wersja:

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;
});

Nieco dłużej z ładnym przejściem krycia:

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>

boska truskawka
źródło
3
Niedoceniane rozwiązanie.
Tom Thomson
1
@TomThomson dzięki Tom, znalazłem, że przejście obrazu nie działa poprawnie, naprawiłem to
Godblessstrawberry
6

Oto mała wtyczka, którą stworzyłem, aby umożliwić ci dokładnie to, działa również na wielu obrazach tła i wielu elementach:

Przeczytaj artykuł:

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

lub przejdź bezpośrednio do kodu wtyczki:

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

Więc po prostu dołącz wtyczkę, a następnie wywołaj ją w elemencie:

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

Oczywiście pobierz wtyczkę i zapisz ją na własnym hostingu.

Domyślnie dodaje dodatkową klasę „bg-load” do każdego dopasowanego elementu po załadowaniu tła, ale możesz to łatwo zmienić, przekazując mu inną funkcję, taką jak ta:

<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>

Oto kodepen pokazujący, że działa.

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

Jon Catmull
źródło
3

Znalazłem rozwiązanie, które działało lepiej dla mnie i które ma tę zaletę, że można je używać z kilkoma obrazami (przypadek nie jest zilustrowany w tym przykładzie).

Z odpowiedzi @ adeneo na to pytanie :

Jeśli masz element z obrazem tła, jak ten

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

Możesz poczekać na załadowanie tła, pobierając adres URL obrazu i używając go jako obiektu obrazu w javascript z funkcją obsługi ładowania

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();
Sok papierowy
źródło
2

Zrobiłem czysty hack javascript, aby to umożliwić.

<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>

Lub

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

css:

.image_error {
    display: none;
}
Gino
źródło