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?


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.


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

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

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


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>


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


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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.