Làm thế nào tôi có thể kiểm tra nếu một hình ảnh nền được tải?


154

Tôi muốn đặt hình nền trên thẻ body, sau đó chạy một số mã - như thế này:

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

Làm thế nào tôi có thể chắc chắn rằng hình nền được tải đầy đủ?


4
Chỉ cần gán cùng một URL cho Image()đối tượng có onloadsự kiện.
Shadow Wizard là Ear For You

2
đảm bảo bọc url css trongurl()
bluescrubbie

Câu trả lời:


274

thử cái này:

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

điều này sẽ tạo ra hình ảnh mới trong bộ nhớ và sử dụng sự kiện tải để phát hiện khi src được tải.


10
Có vẻ như hình ảnh sẽ được tải hai lần mà không có lý do.
ParseA

49
@gAMBOOKa Chúng được tải một lần vì chúng nằm trong bộ nhớ trình duyệt. Điều này cũng tương tự, khi bạn đặt hình ảnh ẩn vào đầu trang và sau đó đặt nó vào CSS - vì vậy hình ảnh bắt đầu tải xuống trước khi tập tin css - nó được gọi là tải trước.
jcubic

4
Tôi không chắc lắm, nhưng tôi nghĩ bạn đang đề cập đến bộ đệm. Tôi không nghĩ có một thứ như bộ nhớ trình duyệt nơi tài sản được lưu trữ. Nếu bạn đang đề cập đến bộ đệm, hãy nhớ rằng bạn đang thêm một yêu cầu HTTP bổ sung và tất cả các máy khách có thể không được bật bộ đệm.
ParseA

7
Nhập cái này vào bất kỳ trang nào có 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)'); }))và kiểm tra các yêu cầu HTTP trong Fireorms. Nếu tôi đã mở trang nhấp nháy với hình ảnh này được mở trong một tab khác thì nó không thực hiện bất kỳ yêu cầu HTTP nào chỉ hiển thị hình ảnh này ngay lập tức. và khi tôi xóa bộ nhớ cache và chạy nó, có một yêu cầu.
jcubic

26
Một so sánh giữa bài kiểm tra nàyđây là một chương trình mà bạn phải gọi .remove()trên $('<img/>')đối tượng để tránh rò rỉ bộ nhớ. Bạn sẽ thấy mức tiêu thụ bộ nhớ ổn định trong lần kiểm tra đầu tiên và tăng bộ nhớ ở lần kiểm tra thứ hai. Sau vài giờ chạy trên Chrome 28, lần thử nghiệm đầu tiên mất 80 MB và lần thứ hai là 270 MB.
benweet

23

Tôi có một plugin jQuery được gọi là waitForImagescó thể phát hiện khi hình ảnh nền đã được tải xuống.

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

Plugin này cũng tuyệt vời để có thể hiển thị tiến trình tải bằng cách sử dụng eachgọi lại.
Soviut

1
@alex, Làm thế nào tôi nên kiểm tra từng hình nền cho từng thành phần trong một lớp? Tôi đã thử điều này nhưng dường như không làm đúng. $ ('. user_main_photo_thumb'). WaitForImages (function () {$ (this) .parents ('. photoThumbFrame'). delay (1000) .slideDown ();}, function (load, Count, thành công) {});
Relm

@Relm Bạn không sử dụng đúng cách. Cuộc gọi lại thứ hai là trên mỗi hình ảnh. Ngoài ra, delay()không làm việc như vậy.
alex

16

Một cái gì đó như thế này:

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

xin chào ... điều này có vẻ hiệu quả, mặc dù tôi đã đặt bg.replace thành bg.replace( ... , my_src ). Nhưng câu hỏi của tôi là: một khi tải $ ('<img>'), điều gì chính xác xảy ra với điều đó <img>... Ý tôi là nó không thực sự - nó chỉ là một trình giữ chỗ giả, phải không?
DSdsdsdsd

Đúng. Không <img>bao giờ được chèn vào DOM; nó chỉ được sử dụng để "đánh lừa" trình duyệt tải tập tin hình ảnh vào bộ đệm.
Colin

hữu ích nếu bạn không muốn gọi jQuery
vwvan


8

giải pháp JS thuần túy sẽ thêm trình tải trước, đặt ảnh nền và sau đó thiết lập nó cho bộ sưu tập rác cùng với trình nghe sự kiện :

Phiên bản ngắn:

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

Một chút nữa với quá trình chuyển đổi độ mờ đẹp:

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
Giải pháp không suy giảm.
Tom Thomson

1
@TomThomson cảm ơn Tom, tôi thấy quá trình chuyển đổi hình ảnh không hoạt động đúng, đã sửa nó
godblessstrawberry

6

Đây là một plugin nhỏ tôi đã tạo để cho phép bạn thực hiện chính xác điều này, nó cũng hoạt động trên nhiều hình nền và nhiều yếu tố:

Đọc bài viết:

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

hoặc đi thẳng đến mã plugin:

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

Vì vậy, chỉ cần bao gồm các plugin và sau đó gọi nó trên phần tử:

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

Rõ ràng tải về các plugin và lưu trữ nó trên lưu trữ của riêng bạn.

Theo mặc định, nó thêm một lớp "bg-load" bổ sung cho mỗi phần tử phù hợp khi nền được tải nhưng bạn có thể dễ dàng thay đổi điều đó bằng cách chuyển cho nó một hàm khác như thế này:

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

Đây là một codepen chứng minh nó hoạt động.

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


3

Tôi đã tìm ra một giải pháp phù hợp hơn với mình và có ưu điểm là có thể sử dụng được với một số hình ảnh (trường hợp không được minh họa trong ví dụ này).

Từ câu trả lời của @ adeneo về câu hỏi này :

Nếu bạn có một yếu tố với hình nền, như thế này

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

Bạn có thể đợi nền tải bằng cách lấy URL hình ảnh và sử dụng nó cho một đối tượng hình ảnh trong javascript với trình xử lý 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

Tôi đã thực hiện một bản hack javascript thuần túy để thực hiện điều này.

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

Hoặc là

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

css:

.image_error {
    display: none;
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.