ฉันจะตรวจสอบได้อย่างไรว่าภาพพื้นหลังโหลดหรือไม่


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
ตรวจสอบให้แน่ใจว่าได้ปิด URL css ในurl()
bluescrubbie

คำตอบ:


274

ลองนี้:

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

สิ่งนี้จะสร้างรูปภาพใหม่ในหน่วยความจำและใช้เหตุการณ์โหลดเพื่อตรวจจับเมื่อโหลด src


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 ได้ไม่กี่ชั่วโมงการทดสอบครั้งแรกจะใช้เวลา 80MB และครั้งที่สอง 270MB
benweet

23

ฉันมีjQuery plugin ที่เรียกwaitForImagesว่าสามารถตรวจจับเมื่อภาพพื้นหลังดาวน์โหลด

$('body')
  .css('background-image','url(http://picture.de/image.png)')
  .waitForImages(function() {
    alert('Background image done loading');
    // This *does* work
  }, $.noop, true);

ปลั๊กอินนี้ยังยอดเยี่ยมสำหรับความสามารถในการแสดงความคืบหน้าการโหลดโดยใช้การeachเรียกกลับ
Soviut

1
@alex ฉันจะตรวจสอบภาพพื้นหลังแต่ละภาพสำหรับแต่ละองค์ประกอบในชั้นเรียนได้อย่างไร ฉันลองสิ่งนี้ แต่ดูเหมือนจะไม่ถูกต้อง $ ('. user_main_photo_thumb'). waitForImages (ฟังก์ชั่น () {$ (นี้) .parents ('. photoThumbFrame'). ความล่าช้า (1000) .slideDown ();}, ฟังก์ชั่น (โหลด, นับ, สำเร็จ) {});
Relm

@Relm คุณใช้งานไม่ถูกต้อง โทรกลับที่สองคือต่อภาพ นอกจากนี้delay()ไม่ทำงานเช่นนั้น
alex

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

สวัสดี ... นี้ดูเหมือนว่าจะทำงาน แต่ผมตั้ง bg.replace bg.replace( ... , my_src )ไป แต่คำถามของฉันคือเมื่อโหลด $ ('<img>') จะเกิดอะไรขึ้นกับสิ่งนั้น<img>... ฉันหมายความว่ามันไม่จริงจริง ๆ - มันเป็นเพียงตัวยึดที่หลอก ๆ ใช่ไหม?
dsdsdsdsd

ขวา. <img>ไม่เคยใส่เข้าไปใน DOM นั้น มันใช้เพื่อ "หลอก" เบราว์เซอร์ในการโหลดไฟล์ภาพลงในแคช
โคลิน

มีประโยชน์หากคุณไม่ต้องการเรียกใช้ jQuery
vwvan

15

ไม่มีการเรียกกลับ JS สำหรับเนื้อหา CSS


3
ขอบคุณสำหรับคำตอบที่รวดเร็ว มีความคิดเห็นใด ๆ สำหรับวิธีแก้ปัญหาหรือไม่
ปีเตอร์

แต่มีวิธีแก้ปัญหา JS สำหรับผู้ที่กำลังมองหาstackoverflow.com/questions/5057990/ …
godblessstrawberry

8

โซลูชัน JS บริสุทธิ์ที่จะเพิ่มตัวโหลดล่วงหน้าตั้งค่าภาพพื้นหลังแล้วตั้งค่าสำหรับการรวบรวมขยะพร้อมกับฟังเหตุการณ์ :

เวอร์ชั่นสั้น:

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>


3
วิธีการแก้ปัญหาที่ underrated
Tom Thomson

1
@ Tomom Thomson ขอบคุณ Tom ฉันพบว่าการเปลี่ยนภาพไม่ทำงานอย่างถูกต้องแก้ไขมัน
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" เพิ่มเติมให้กับองค์ประกอบที่ตรงกันแต่ละครั้งเมื่อโหลดพื้นหลัง แต่คุณสามารถเปลี่ยนได้โดยง่ายผ่านฟังก์ชั่นต่าง ๆ ดังนี้:

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

นี่คือ codepen ที่แสดงให้เห็นว่ามันทำงานได้

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


3

ฉันพบวิธีแก้ปัญหาที่ใช้งานได้ดีกว่าสำหรับฉันและมีข้อได้เปรียบในการใช้งานกับรูปภาพหลายรูป (กรณีไม่ได้แสดงในตัวอย่างนี้)

จากคำตอบของ @ adeneo สำหรับคำถามนี้ :

หากคุณมีองค์ประกอบที่มีภาพพื้นหลังเช่นนี้

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

คุณสามารถรอให้พื้นหลังโหลดโดยรับ URL รูปภาพและใช้เป็นวัตถุรูปภาพใน javascript พร้อมตัวจัดการ onload

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

ฉันแฮ็คจาวาสคริปต์ที่บริสุทธิ์เพื่อให้เป็นไปได้

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.