How can I check if a background image is loaded?
I want to set a background image on the body tag, then run some code - like this:
$('body').css('background-image','http://picture.de/image.png').load(functio开发者_如何学运维n() {
alert('Background image done loading');
// This doesn't work
});
How can I make sure the background image is fully loaded?
try this:
$('<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)');
});
this will create a new image in memory and use load event to detect when the src is loaded.
EDIT: in Vanilla JavaScript it can look like this:
var src = 'http://picture.de/image.png';
var image = new Image();
image.addEventListener('load', function() {
body.style.backgroundImage = 'url(' + src + ')';
});
image.src = src;
it can be abstracted into handy function that return a promise:
function load(src) {
return new Promise((resolve, reject) => {
const image = new Image();
image.addEventListener('load', resolve);
image.addEventListener('error', reject);
image.src = src;
});
}
const image = 'http://placekitten.com/200/300';
load(image).then(() => {
body.style.backgroundImage = `url(${image})`;
});
I have a jQuery plugin called waitForImages
that can detect when background images have downloaded.
$('body')
.css('background-image','url(http://picture.de/image.png)')
.waitForImages(function() {
alert('Background image done loading');
// This *does* work
}, $.noop, true);
pure JS solution that will add preloader, set the background-image and then set it up for garbage collection along with it's event listener:
Short version:
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;
});
A bit longer with nice opacity transition:
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>
There are no JS callbacks for CSS assets.
Something like this:
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();
});
}
});
I've located a solution that worked better for me, and which has the advantage of being usable with several images (case not illustrated in this example).
From @adeneo's answer on this question :
If you have an element with a background image, like this
<div id="test" style="background-image: url(link/to/image.png)"><div>
You can wait for the background to load by getting the image URL and using it for an image object in javascript with an onload handler
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();
Here is a small plugin I made to allow you to do exactly this, it also works on multiple background images and multiple elements:
Read the article:
http://catmull.uk/code-lab/background-image-loaded/
or go straight to the plugin code:
http://catmull.uk/downloads/bg-loaded/bg-loaded.js
So just include the plugin and then call it on the element:
<script type="text/javascript" src="http://catmull.uk/downloads/bg-loaded/bg-loaded.js"></script>
<script type="text/javascript">
$('body').bgLoaded();
</script>
Obviously download the plugin and store it on your own hosting.
By default it adds an additional "bg-loaded" class to each matched element once the background is loaded but you can easily change that by passing it a different function like this:
<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>
Here is a codepen demonstrating it working.
http://codepen.io/catmull/pen/Lfcpb
I did a pure javascript hack to make this possible.
<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>
Or
onerror="this.parentElement.backgroundImage = "url('image_placeHolder.png')";
css:
.image_error {
display: none;
}
https://github.com/alexanderdickson/waitForImages
$('selector').waitForImages({
finished: function() {
// ...
},
each: function() {
// ...
},
waitForAll: true
});
Here is a simple vanilla hack ~
(function(image){
image.onload = function(){
$(body).addClass('loaded-background');
alert('Background image done loading');
// TODO fancy fade-in
};
image.src = "http://picture.de/image.png";
})(new Image());
精彩评论