How to create a JavaScript callback for knowing when an image is loaded?

JavascriptImageCallbackLoading

Javascript Problem Overview


I want to know when an image has finished loading. Is there a way to do it with a callback?

If not, is there a way to do it at all?

Javascript Solutions


Solution 1 - Javascript

.complete + callback

This is a standards compliant method without extra dependencies, and waits no longer than necessary:

var img = document.querySelector('img')

function loaded() {
  alert('loaded')
}

if (img.complete) {
  loaded()
} else {
  img.addEventListener('load', loaded)
  img.addEventListener('error', function() {
      alert('error')
  })
}

Source: http://www.html5rocks.com/en/tutorials/es6/promises/

Solution 2 - Javascript

Image.onload() will often work.

To use it, you'll need to be sure to bind the event handler before you set the src attribute.

Related Links:

Example Usage:

    window.onload = function () {

        var logo = document.getElementById('sologo');

        logo.onload = function () {
            alert ("The image has loaded!");		
        };

        setTimeout(function(){
            logo.src = 'https://edmullen.net/test/rc.jpg';         
        }, 5000);
    };

 <html>
    <head>
    <title>Image onload()</title>
    </head>
    <body>

    <img src="#" alt="This image is going to load" id="sologo"/>

    <script type="text/javascript">

    </script>
    </body>
    </html>

Solution 3 - Javascript

You can use the .complete property of the Javascript image class.

I have an application where I store a number of Image objects in an array, that will be dynamically added to the screen, and as they're loading I write updates to another div on the page. Here's a code snippet:

var gAllImages = [];

function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
{
    gAllImages = [];

    for (var i = thumbnailsBegin; i < thumbnailsEnd; i++) 
    {
        var theImage = new Image();
        theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
        gAllImages.push(theImage);
    
        setTimeout('checkForAllImagesLoaded()', 5);
        window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;
    
        // make a new div containing that image
        makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
    }
}

function checkForAllImagesLoaded()
{
    for (var i = 0; i < gAllImages.length; i++) {
        if (!gAllImages[i].complete) {
            var percentage = i * 100.0 / (gAllImages.length);
            percentage = percentage.toFixed(0).toString() + ' %';
        
            userMessagesController.setMessage("loading... " + percentage);
            setTimeout('checkForAllImagesLoaded()', 20);
            return;
        }
    }

    userMessagesController.setMessage(globals.defaultTitle);
}

Solution 4 - Javascript

Life is too short for jquery.

function waitForImageToLoad(imageElement){
  return new Promise(resolve=>{imageElement.onload = resolve})
}

var myImage = document.getElementById('myImage');
var newImageSrc = "https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620"

myImage.src = newImageSrc;
waitForImageToLoad(myImage).then(()=>{
  // Image have loaded.
  console.log('Loaded lol')
});

<img id="myImage" src="">

Solution 5 - Javascript

You could use the load()-event in jQuery but it won't always fire if the image is loaded from the browser cache. This plugin https://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js can be used to remedy that problem.

Solution 6 - Javascript

Here is jQuery equivalent:

var $img = $('img');

if ($img.length > 0 && !$img.get(0).complete) {
   $img.on('load', triggerAction);
}

function triggerAction() {
   alert('img has been loaded');
}

Solution 7 - Javascript

Not suitable for 2008 when the question was asked, but these days this works well for me:

async function newImageSrc(src) {
  // Get a reference to the image in whatever way suits.
  let image = document.getElementById('image-id');

  // Update the source.
  img.src = src;

  // Wait for it to load.
  await new Promise((resolve) => { image.onload = resolve; });

  // Done!
  console.log('image loaded! do something...');
}

Solution 8 - Javascript

If the goal is to style the img after browser has rendered image, you should:

const img = new Image();
img.src = 'path/to/img.jpg';

img.decode().then(() => {
/* set styles */
/* add img to DOM */ 
});

because the browser first loads the compressed version of image, then decodes it, finally paints it. since there is no event for paint you should run your logic after browser has decoded the img tag.

Solution 9 - Javascript

these functions will solve the problem, you need to implement the DrawThumbnails function and have a global variable to store the images. I love to get this to work with a class object that has the ThumbnailImageArray as a member variable, but am struggling!

called as in addThumbnailImages(10);

var ThumbnailImageArray = [];

function addThumbnailImages(MaxNumberOfImages)
{
	var imgs = [];

	for (var i=1; i<MaxNumberOfImages; i++)
	{
		imgs.push(i+".jpeg");
	}

	preloadimages(imgs).done(function (images){
			var c=0;
		
			for(var i=0; i<images.length; i++)
			{
				if(images[i].width >0) 
				{
					if(c != i)
						images[c] = images[i];
					c++;
				}
			}
		
			images.length = c;
		
			DrawThumbnails();
		});
}



function preloadimages(arr)
{
	var loadedimages=0
	var postaction=function(){}
	var arr=(typeof arr!="object")? [arr] : arr

	function imageloadpost()
	{
		loadedimages++;
		if (loadedimages==arr.length)
		{
			postaction(ThumbnailImageArray); //call postaction and pass in newimages array as parameter
		}
	};

	for (var i=0; i<arr.length; i++)
	{
		ThumbnailImageArray[i]=new Image();
		ThumbnailImageArray[i].src=arr[i];
		ThumbnailImageArray[i].onload=function(){ imageloadpost();};
		ThumbnailImageArray[i].onerror=function(){ imageloadpost();};
	}
	//return blank object with done() method	
	//remember user defined callback functions to be called when images load
	return 	{ done:function(f){ postaction=f || postaction } };
}

Solution 10 - Javascript

If you are using React.js, you could do this:

render() {

// ...

<img 
onLoad={() => this.onImgLoad({ item })}
onError={() => this.onImgLoad({ item })}

src={item.src} key={item.key}
ref={item.key} />

// ... }

Where:

  • - onLoad (...) now will called with something like this: { src: "https://......png", key:"1" } you can use this as "key" to know which images is loaded correctly and which not.
  • - onError(...) it is the same but for errors.
  • - the object "item" is something like this { key:"..", src:".."} you can use to store the images' URL and key in order to use in a list of images.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmattView Question on Stackoverflow
Solution 1 - JavascriptCiro Santilli Путлер Капут 六四事View Answer on Stackoverflow
Solution 2 - JavascriptkeparoView Answer on Stackoverflow
Solution 3 - JavascriptJon DellOroView Answer on Stackoverflow
Solution 4 - JavascriptIdan BekerView Answer on Stackoverflow
Solution 5 - JavascriptjimmystormigView Answer on Stackoverflow
Solution 6 - JavascriptAlexander DrobyshevskyView Answer on Stackoverflow
Solution 7 - JavascriptHughView Answer on Stackoverflow
Solution 8 - JavascriptSajadView Answer on Stackoverflow
Solution 9 - JavascriptdaveView Answer on Stackoverflow
Solution 10 - JavascriptMikeView Answer on Stackoverflow