Go JavaScript implements pre-loading of pictures

Source: Internet
Author: User
Tags closure browser cache

Do the picture flipping effect of friends actually know, want to let the picture rotation time does not appear waits, the best is to let the picture download to local, let the browser cache up. At this time, the general will use JS inside the image object. The general means is nothing more than this:

function preloadimg (URL) {
var img = new Image ();
Img.src = url;
}


By calling the Preloadimg function and passing in the URL of the image, the image can be pre-downloaded. In fact, the pre-download functionality used here is basically consistent with this. After the image is pre-downloaded, the width and height properties of the IMG will tell you the width and height of the image. But take into account, in the Image browser function, the picture is displayed in real time. For example, if you click on the button to display, this time it will invoke similar code above to load the image. Therefore, if you use Img.width directly, the picture is not fully downloaded. Therefore, it is necessary to use some asynchronous methods to wait until the picture is downloaded, and then the width and height of the IMG will be called.

The implementation of such an asynchronous method is not really difficult, the download of the picture is also very simple event is simple onload event. Therefore, we can write the following code:

functionLoadImage (URL, callback){
VarImg= new image ();
  img.src = url;

  img.onload = function () { //
    callback.call (IMG);    //  Switches the callback function this pointer to IMG.
  }}



Well, then write a test case.

function imgloaded () {
alert (this.width);
}
<input type= "button" value= "LoadImage" onclick= "LoadImage (' aaa.jpg ', imgloaded)" />


Test in Firefox, found good, sure enough and the expected effect, after the picture is downloaded, it will pop up the width of the image. No matter how many times you click or refresh the results are the same.

However, do this step, don't be happy too early-also need to consider the browser compatibility, so, quickly to IE inside test. Yes, it also pops up the width of the image. However, when you click Load again, the situation is different and nothing happens. Refresh, and the same is true.

After testing multiple browser versions, IE6 and opera were found to be the same, while Firefox and Safari behaved normally. In fact, the reason is quite simple, because the browser cache. Once the picture has been loaded once, if there is another request for the picture, because the browser has already cached the image, it will not initiate a new request again, but is loaded directly from the cache. For both Firefox and Safari, the view makes the two loading methods transparent to the user, which also causes the OnLoad event of the picture, while IE and opera ignore this identity and do not cause the image's OnLoad event, so the above code cannot be implemented in them.

What do we do? The best case is that the image can have a status value indicating whether it has been loaded successfully. When loading from the cache, because there is no need to wait, the status value directly indicates that it has been downloaded, while loading from the HTTP request, because it needs to wait for the download, this value is displayed as incomplete. In that case, you can take care of it.

After some analysis, we finally found a property--complete for the image that is compatible with each browser. So, before the image onload event, make a judgment on this value. Finally, the code changes to look like this:

functionLoadImage (URL, callback){
VarImg=NewImage ();//Create an Image object that enables pre-download of pictures
Img.src=Url

If(Img.complete){//If the picture already exists in the browser cache, call the callback function directly
Callback.call (IMG);
Return;//Return directly without handling the OnLoad event
&NBSP;&NBSP;&NBSP;&NBSP;}

    img.onload =< Span style= "color: #000000;" > function  ()  { // The callback function is called asynchronously when the picture is downloaded.
         callback.call (IMG); // Replace the this callback function with the image object     }}


After such a toss-up, it is finally let each browser can meet our goal. Although the code is simple, but the most important problem in the image browser is solved, and then you have to do is just how the picture presents the problem.

The code is as follows:

functionLoadImage (URL, callback) {
VarImg= new Image (); // Create an Image object that enables pre-download of the picture
img.src = URL;

if (Img.complete) { // If the picture already exists in the browser cache, call the callback function directly
callback (IMG);
return; // return directly without handling the onload event
/span> img.onload = function () {// Asynchronously calls the callback function when the picture is downloaded.
Callback (IMG)
}; < Span style= "color: #000000;" >< Span style= "color: #0000ff;" >< Span style= "color: #008000;" >
};

On the Internet to search the relevant articles, in general, this is the idea.

This method function is OK, but there are some pitfalls.

1 creates a temporary anonymous function to act as the OnLoad event handler for a picture, forming a closure.

I believe that everyone has seen the memory leak mode under IE, one of the patterns is circular reference, and the closure has the ability to save the external operating environment (dependent on the implementation of the scope chain), so Img.onload This function also holds a reference to the IMG, which forms a circular reference that causes a memory leak. (This pattern of memory leaks only exists in the lower version of the IE6, the patched IE6 and the higher versions of IE all address the memory leaks caused by circular references).

2 only take into account the loading of static images, ignoring animated images such as GIF, these dynamic pictures may trigger onload multiple times.

To solve the above two problems is very simple, actually very simple, the code is as follows:

Img.onload = function () { /////The picture is downloaded asynchronously when callback functions are called.
Img.onload = null;
Callback (IMG);
};

This can solve the problem of memory leak, but also can avoid the event of the dynamic picture multiple triggering problem.

In some related blog posts, it has also been noted that to set Img.onload to NULL, but the timing is not right, most of the articles are callback run after the img.onload is set to NULL, so that although the problem of circular reference, but for the dynamic picture , if the callback run more time-consuming, there are many times triggered the hidden trouble.

The hidden trouble is eliminated after the above modification, but there is room for optimization in this code:

if (img.complete) { // If the picture already exists in the browser cache, call the callback function directly
Callback (IMG);
return; // return directly, no more handling onload events
}

For this code, see the relevant it narrative, for the following reasons:

after a number of browser versions of the test, found under IE, Opera, when the picture has been loaded once, if there is a request for the picture, because the browser has cached this image A new request is not initiated, but is loaded directly from the cache. For Firefox and Safari, they try to make the two load modes transparent to the user, as well will cause the image onload event, and IE and opera ignore this identity, will not cause the image onload event, so the above code in their inside can not be real The current effect.

Indeed, under Ie,opera, the initial state of the cached picture is not the same as Firefox and Safari,chrome (if you are interested, you can test the status of IMG before the URL of the SRC assignment cache image to img in different browsers), But the triggering of the OnLoad event is consistent, no matter what browser it is. The root cause of this problem is that the IMG src assignment is bound to the OnLoad event in the wrong order (in IE and opera, the first assignment is SRC, then the onload, because it is a cached image, it misses the OnLoad event trigger). The OnLoad event should be bound first and then assigned to SRC, with the following code:

function LoadImage (URL, callback) {
var img = new Image (); // Create an Image object that enables pre-download of the picture
img.onload = function () {
Img.onload = null;
Callback (IMG);
}
img.src = URL;
} /span>   This memory leak, dynamic picture loading problems have been solved, but also in a unified manner, the implementation of the callback call.

Go JavaScript implements pre-loading of pictures

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.