Image Preloader JavaScript That Supports Events

Image preloader javascript that supports events

Here's a function that will preload images from an array and call your callback when the last one has finished:

function preloadImages(srcs, imgs, callback) {
var img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
img.onload = function() {
--remaining;
if (remaining <= 0) {
callback();
}
};
img.src = srcs[i];
imgs.push(img);
}
}

// then to call it, you would use this
var imageSrcs = ["src1", "src2", "src3", "src4"];
var images = [];

preloadImages(imageSrcs, images, myFunction);

And since we're now in the age of using promises for asynchronous operations, here's a version of the above that uses promises and notifies the caller via an ES6 standard promise:

function preloadImages(srcs) {
function loadImage(src) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.onload = function() {
resolve(img);
};
img.onerror = img.onabort = function() {
reject(src);
};
img.src = src;
});
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return Promise.all(promises);
}

preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) {
// all images are loaded now and in the array imgs
}, function(errImg) {
// at least one image failed to load
});

And, here's a version using 2015 jQuery promises:

function preloadImages(srcs) {
function loadImage(src) {
return new $.Deferred(function(def) {
var img = new Image();
img.onload = function() {
def.resolve(img);
};
img.onerror = img.onabort = function() {
def.reject(src);
};
img.src = src;
}).promise();
}
var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return $.when.apply($, promises).then(function() {
// return results as a simple array rather than as separate arguments
return Array.prototype.slice.call(arguments);
});
}

preloadImages(["src1", "src2", "src3", "src4"]).then(function(imgs) {
// all images are loaded now and in the array imgs
}, function(errImg) {
// at least one image failed to load
});

Preloading images with JavaScript

Yes. This should work on all major browsers.

Preloading images in an array (and waiting until they have downloaded)

Here's a much, much simpler way to preload images and have it call a callback when the images are done loading in a related prior question/answer: Image preloader javascript that supports events.

onerror event not being detected during image preloading?

onerror is asynchronous. It happens sometime in the future. You are testing the valid variable long before onerror or onload has even run. If you only want to push good images into the array, then you should just push them into the array in the onload handler like this:

for(i = 0; i < imgURLs.length; i++) {
var img = new Image();
img.onload = function(){
console.log('New Media Loaded')
goodArray.push(this);
};
img.onerror = function(){
console.log('error: bad image source');
};
img.src = url;
}

FYI. Note, I'm also pushing this, not img because the variable img has been changed by the subsequent iterations of your for loop, but this will be the image that just successfully loaded.


If you want an image preloader that will notify when the last image has loaded, you can use the code form this answer.

Caching preloaded images possible over page switch?

The browser already caches the images in its memory and/or disk cache as long as the headers coming from the server aren't telling it to avoid caching. The browser cache endures across page loads. SO, if your images have been loaded once on the first page, they should be in the browser cache already for the second page and thus when requested on the second page, they should load locally and not have to be fetched over the internet.

If you're looking for client-side code that can be used to preload images, there are many examples:

How do you cache an image in Javascript

Image preloader javascript that supports events

Is there a way to load images to user's cache asynchronously?

FYI, it is possible in newer browsers to use a combination of Local Storage and data URIs to implement your own image caching, but I'd be surprised if there was any real world situation where that was required and if you have a lot of images, you may run into storage limits on Local Storage quicker than limits on the size of the browser cache.

Fire an event after preloading images

You can use the new "$.Deferred" if you like:

var preload = ["a.gif", "b.gif", "c.gif"];
var promises = [];
for (var i = 0; i < preload.length; i++) {
(function(url, promise) {
var img = new Image();
img.onload = function() {
promise.resolve();
};
img.src = url;
})(preload[i], promises[i] = $.Deferred());
}
$.when.apply($, promises).done(function() {
alert("All images ready sir!");
});

Might be a little risky to leave the Image objects floating around, but if so that could be fixed easily by shifting the closure. edit in fact I'll change it myself because it's bugging me :-)

JQuery - Preload Images (using JQuery / native JavaScript / CSS)

You can preload an image quite easily as follows:

using JQuery

function preloadImg(src) {
$('<img/>')[0].src = src;
}

preloadImg('http://yoururl/to/the/picture.jpg');

or Native Javascript

function preloadImg(src) {
var img = new Image();
img.src = src;
}

preloadImg('http://yoururl/to/the/picture.jpg');

or Using CSS (no JavaScript required)

You can also preload images using CSS (and HTML)

CSS:
div#preload { display: none; }

HTML:

<div id="preload">
<img src="http://yoururl/to/the/picture1.jpg" width="1" height="1" alt="Image 1" />
<img src="http://yoururl/to/the/picture2.jpg" width="1" height="1" alt="Image 2" />
<img src="http://yoururl/to/the/picture3.jpg" width="1" height="1" alt="Image 3" />
</div>

Preloading images with jQuery

Quick and easy:

function preload(arrayOfImages) {
$(arrayOfImages).each(function(){
$('<img/>')[0].src = this;
// Alternatively you could use:
// (new Image()).src = this;
});
}

// Usage:

preload([
'img/imageName.jpg',
'img/anotherOne.jpg',
'img/blahblahblah.jpg'
]);

Or, if you want a jQuery plugin:

$.fn.preload = function() {
this.each(function(){
$('<img/>')[0].src = this;
});
}

// Usage:

$(['img1.jpg','img2.jpg','img3.jpg']).preload();

Retrieve preloaded image from cached array

You're going to have to make sure you can somehow retrieve the img elements you've preloaded. There are many ways to do this but three that come to mind straight away.

1. Added loaded image in the DOM

In your example you're trying to retrieve the images with a query selector. This fails because the img elements aren't added to the DOM. You could attach them to a DOM element that is hidden from the user.

var 
images = [
{
src: '//placehold.it/550x250?text=A',
top: 0,
class:'img-a' // unique class name to retrieve item using a query selector.
},
{
src: '//placehold.it/550x250?text=B',
top: 0,
class:'img-b'
}],
imageCache = document.getElementById('image-cache');

function preloadImages(srcs) {
function loadImage(imgToLoad) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.onload = function() {
// The image has been loaded, add it to the cache element.
imageCache.appendChild(img);
resolve(img);
};
img.onerror = img.onabort = function() {
reject(imgToLoad.src);
};
img.className = 'testimg ' + imgToLoad.class; //Test to see if I can retrieve img
img.src = imgToLoad.src;
img.style.top = imgToLoad.top;
});
}

var promises = [];
for (var i = 0; i < srcs.length; i++) {
promises.push(loadImage(srcs[i]));
}
return Promise.all(promises);
}

// Load all the images.
preloadImages(images)
.then(result => {
// Add img B from the cache to the proof div.
document.getElementById('proof').appendChild(imageCache.querySelector('.img-b'));
});
.hidden { 
display: none;
}
<div id="image-cache" class="hidden"></div>
<div id="proof"></div>


Related Topics



Leave a reply



Submit