2

Is there a way in vanilla Javascript to wait until an image is completely rendered before continuing execution? I need this to occur after the document has already been loaded. According to Is there something like a ready event when an image in html is loaded and rendered?, the document's load event waits for rendering to finish. However, I need to load images after the document has been initially loaded.

People seem to say to use the load event on the image element. However, the element's load event only detects when an image is loaded, not when it has finished rendering.

For example, I have an image tag set to the size of the viewport:

<img id="test" style="width: 100vw; height: 100vh;"></img>

The following code then loads an extremely large image into the tag (the image I am testing on is specifically 7360x4912, but the process should work for all image sizes):

var img = document.getElementById("test");
img.addEventListener("load", function () {
    alert("Image is loaded but not necessarily rendered");
});
img.src = "ExtremelyLargeImage.jpg";

However, when the event is fired, the image is not fully rendered (i.e., it is displayed as either completely white or partially white).

Avoiding using an arbitrarily-long setTimeout is critical here, especially because render times may be drastically different between PC and mobile browsers.

Finally, I am aware that different image sizes can be served to different screen sizes rather than using just one large image for all screens. However, for this purpose, I must be able to detect when an image has completed rendering, so the actual image size is irrelevant.

Edit 1: I adding requestAnimationFrame within the load callback, putting the alert into the callback for requestAnimationFrame:

var img = document.getElementById("test");
img.addEventListener("load", function () {
    requestAnimationFrame(function () {
        alert("Image load");
    });
});
img.src = "ExtremelyLargeImage.jpg";

As expected, this does not work because requestAnimationFrame executes its callback before the next repaint.

Edit 2:

Adding a second requestAnimationFrame layer in the stack has the same issue that just having one has. Basically, now it is executing the alert between the first and second repaints rather than just before the first. However, there is no guarantee that the image has been completely painted by then. It is an improvement, though.

var img = document.getElementById("test");
img.addEventListener("load", function () {
    requestAnimationFrame(function () {
        requestAnimationFrame(function () {         
            alert("Image load");
        });
    });
});
img.src = "ExtremelyLargeImage.jpg";
Jonathan
  • 326
  • 3
  • 12
  • 1
    Possible duplicate of [Is there something like a ready event when an image in html is loaded and rendered?](https://stackoverflow.com/questions/8262916/is-there-something-like-a-ready-event-when-an-image-in-html-is-loaded-and-render) – Andreas Nov 22 '18 at 04:12
  • Just add a [`requestAnimationFrame()`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) callback within the `load` event listener. – Patrick Roberts Nov 23 '18 at 20:02
  • @PatrickRoberts I edited the question to include requestAnimationFrame. Please make sure I implemented as you had intended. My understanding of requestAnimationFrame is still limited and the implementation does not work. – Jonathan Nov 25 '18 at 00:47
  • Can you actually create a [mcve]? – Patrick Roberts Nov 25 '18 at 01:05
  • 1
    Possible duplicate of [How to detect when an image has finished rendering in the browser (i.e. painted)?](https://stackoverflow.com/questions/14578356/how-to-detect-when-an-image-has-finished-rendering-in-the-browser-i-e-painted) – Patrick Roberts Nov 25 '18 at 02:04

2 Answers2

0

The trouble with the requestAnimationFrame() can be that after event load an img will be rendered on second animation frame. So you were on the right path, just call another function on first requestAnimationFrame

So you could try something like this:

<script>
function rendered() {
    //Render complete
    alert("image rendered");
}

function startRender() {
    //Rendering start
    requestAnimationFrame(rendered);
}

function loaded()  {
    requestAnimationFrame(startRender);
}

<img onload="loaded();" src="http://ximmix.mixeriksson.com/bilder/iron_maiden_piece_of_mind_foldout_cleaned_3034x1500px_110412145556_2.jpg">

If it works give also credits to #Hovitya this post

This is his jsfiddle example

Adam Orłowski
  • 4,268
  • 24
  • 33
  • Instead of reposting duplicated content, you should close-vote the question as a duplicate if the exact answer you're copying answers the question as-is. – Patrick Roberts Nov 25 '18 at 02:04
  • See edit 2. Although this is helpful, it does not solve the underlying issue. – Jonathan Nov 26 '18 at 05:59
0

Use load event.

$("img#test").on("load", function(event){
    //enter your code here
})
devsong
  • 1
  • 3
  • 1
    Your solution uses jQuery which is outside the scope of the question. Although I haven't tested against jQuery's "load" handler, JavaScript's load event does not detect when the image finishes rendering, so I assume the jQuery handler would be the same. – Jonathan Feb 02 '21 at 22:59