首页 > 解决方案 > Waiting for an image to finish rendering

问题描述

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";

标签: javascript

解决方案


使用加载事件。

$("img#test").on("load", function(event){
    //enter your code here
})

推荐阅读