Reliable image load events with load_image
Wow! This takes me back! Please check the date this post was authored, as it may no longer be relevant in a modern context.
For several months I’ve been working with To Be, building a platform for creating and sharing creative work online. To Be’s fields are very visual, often incorporating animated GIFs, static images, canvas-rendered images, and iframes. Check out this field to see what kind of things people are creating and look here for more fields.
When images are loaded for a To Be field, we often need to react to the loaded state and perform some action. For instance if a given field element has a stencil description, we load the image to a canvas and process that canvas as a stencil. It turns out that image load events are notoriously un-reliable. For instance Chrome will not fire an onload
callback when an image is fetched from the local cache [ticket here].
Last fall, I published a small library called after_image_load
to GitHub. It handled CORs headers in addition to ensuring load events are always fired. We’ve been using that library in production for almost half a year now, and today I’ve finally incorporated the lessons from using it into an even slimmer jQuery library called load_image
. Check it out on GitHub, and read on for some example usage.
Using load_image
load_image
follows jQuery plugin conventions and returns a jQuery.Deferred
promise [jQuery.Deferred docs]. Usage is simple:
$.loadImage("http://example.com/cat-photo.jpg").done(function(img){
// `img` is a jQuery wrapped image element.
img.appendTo('.wrapper');
});
We often use the image loader with CORs so images from other domains can be safely added to canvas elements. For this, the easiest thing to do is call loadImage
on a new element you create:
$('<img crossOrigin="Anonymous" />').loadImage("http://example.com/cat-photo.jpg").done(function(img){
// `img` has been loaded with CORs
});
Image elements cannot have their crossOrigin property changed, so you must create a new element if this value changes. Specifically you cannot un-set the crossOrigin
value.
We also often need to fire CORs for an image URL, but not for a data-url:
// Assumes url... could be a data-url or a real URL.
imageElement = $(url.indexOf('data:') === 0 ? '<img />' : '<img crossOrigin="Anonymous" />');
imageElement.loadImage(url).done(function(img){
// `img` has been loaded with CORs, only
// if it was not a data-url.
});
We’ve found this to be a small but helpful tool for building To Be. Hope you find it useful!