Bagaimana saya dapat memeriksa apakah gambar latar belakang dimuat?

154

Saya ingin mengatur gambar latar belakang pada tag tubuh, kemudian jalankan beberapa kode - seperti ini:

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

Bagaimana saya bisa memastikan gambar latar belakang dimuat penuh?

Peter
sumber
4
Cukup tetapkan URL yang sama ke Image()objek yang memiliki onloadacara.
Shadow Wizard adalah Ear For You
2
pastikan untuk membungkus url css inurl()
bluescrubbie

Jawaban:

274

coba ini:

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

ini akan membuat gambar baru di memori dan menggunakan memuat acara untuk mendeteksi ketika src dimuat.

jcubic
sumber
10
Sepertinya gambar akan dimuat dua kali tanpa alasan.
HyderA
49
@gAMBOOKa Mereka dimuat sekali karena tetap di memori browser. Ini sama, ketika Anda meletakkan gambar tersembunyi di atas halaman Anda dan kemudian mengaturnya di CSS - sehingga gambar mulai diunduh sebelum file css - itu disebut preloading.
jcubic
4
Saya tidak terlalu yakin, tapi saya pikir Anda mengacu pada cache. Saya tidak berpikir ada yang namanya memori browser tempat aset disimpan. Jika Anda merujuk ke cache, ingatlah bahwa Anda menambahkan permintaan HTTP tambahan dan semua klien mungkin tidak mengaktifkan cache.
HyderA
7
Masukkan ini di halaman mana saja yang memiliki 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)'); }))dan periksa permintaan HTTP di Firebug. Jika saya telah membuka halaman flicker dengan gambar ini dibuka di tab lain itu tidak melakukan permintaan HTTP apa pun hanya menampilkan gambar ini secara instan. dan ketika saya menghapus cache dan menjalankannya ada satu permintaan.
jcubic
26
Perbandingan antara tes ini dan ini salah satu menunjukkan bahwa Anda harus menelepon .remove()pada $('<img/>')objek untuk menghindari kebocoran memori. Anda akan melihat konsumsi memori yang stabil pada tes pertama dan peningkatan memori pada tes kedua. Setelah beberapa jam berjalan di Chrome 28, pengujian pertama membutuhkan 80MB dan yang kedua 270MB.
benweet
23

Saya memiliki plugin jQuery yang disebut waitForImagesyang dapat mendeteksi kapan gambar latar belakang diunduh.

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);
alex
sumber
Plugin ini juga bagus untuk dapat menampilkan progres pemuatan menggunakan eachcallback.
Soviut
1
@ alex, Bagaimana saya harus memeriksa setiap gambar latar belakang untuk setiap elemen di kelas? Saya mencoba ini tetapi tampaknya tidak melakukannya dengan benar. $ ('. user_main_photo_thumb'). waitForImages (function () {$ (this) .parents ('. photoThumbFrame'). keterlambatan (1000) .slideDown ();}, fungsi (dimuat, hitung, sukses) {});
Relm
@Relm Anda tidak menggunakannya dengan benar. Callback kedua adalah per gambar. Juga, delay()tidak berfungsi seperti itu.
alex
16

Sesuatu seperti ini:

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
sumber
halo ... ini sepertinya berhasil, meskipun saya atur bg.replace ke bg.replace( ... , my_src ). Tapi pertanyaan saya adalah: setelah $ ('<img>') dimuat, apa yang sebenarnya terjadi dengan itu <img>... Maksud saya itu tidak benar-benar nyata - itu hanya penampung dummy, kan?
dsdsdsdsd
Baik. Itu <img>tidak pernah dimasukkan ke dalam DOM; itu hanya digunakan untuk "menipu" browser agar memuat file gambar ke dalam cache.
Colin
membantu jika Anda tidak ingin memohon jQuery
vwvan
15

Tidak ada callback JS untuk aset CSS.

Adrian Pacala
sumber
3
Terima kasih atas jawaban cepatnya. Ada ide untuk solusi penyelesaiannya?
Peter
tetapi ada solusi JS untuk mereka yang mencari stackoverflow.com/questions/5057990/...
godblessstrawberry
8

solusi JS murni yang akan menambahkan preloader, mengatur gambar latar belakang dan kemudian mengaturnya untuk pengumpulan sampah bersama dengan pendengar acara itu :

Versi pendek:

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

Sedikit lebih lama dengan transisi opacity yang bagus:

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
sumber
3
Solusi yang diremehkan.
Tom Thomson
1
@TomThomson terima kasih Tom, saya menemukan transisi gambar tidak berfungsi dengan baik, memperbaikinya
godblessstrawberry
6

Ini adalah plugin kecil yang saya buat untuk memungkinkan Anda melakukan hal ini, itu juga berfungsi pada banyak gambar latar belakang dan beberapa elemen:

Baca artikel:

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

atau langsung ke kode plugin:

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

Jadi cukup sertakan plugin dan panggil saja pada elemen:

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

Jelas unduh plugin dan simpan di hosting Anda sendiri.

Secara default ia menambahkan kelas "bg-loaded" tambahan untuk setiap elemen yang cocok setelah latar belakang dimuat tetapi Anda dapat dengan mudah mengubahnya dengan melewatkannya fungsi yang berbeda seperti ini:

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

Berikut ini adalah codepen yang menunjukkan itu berfungsi.

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

Jon Catmull
sumber
3

Saya telah menemukan solusi yang bekerja lebih baik untuk saya, dan yang memiliki keuntungan dapat digunakan dengan beberapa gambar (case tidak diilustrasikan dalam contoh ini).

Dari jawaban @ adeneo pada pertanyaan ini :

Jika Anda memiliki elemen dengan gambar latar belakang, seperti ini

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

Anda bisa menunggu latar belakang untuk memuat dengan mendapatkan URL gambar dan menggunakannya untuk objek gambar dalam javascript dengan penangan yang memuat

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

Saya melakukan hack javascript murni untuk membuat ini mungkin.

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

Atau

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

css:

.image_error {
    display: none;
}
Gino
sumber