简体   繁体   中英

HTML5 Canvas toDataURL() blocks JavaScript Call?

I am using HTML5 Canvas. I have loaded an image of size 7MB inside a canvas element. On my page I have a ConvertImage button:

var imageUrl;
$("#ConvertImage").click(function() {
  $("#Spinner").show();
  imageUrl = $("#canvas")[0].toDataURL("image/png;base64;");
});

The Spinner is just an animated gif. It turns out that the Spinner is not shown right away when I try to retrieve the imageUrl in the next statement. Without the second operation the spinner is shown right away. It feels like the spinner is shown after the toDataURL() operation is completed.

This is strange because the show() function is executed before the toDataURL() operation.

How can I fix this problem?

For updating the spinner, try to modify the code so that an extra update event is created.

You can do this by using setTimeout :

$("#ConvertImage").click(function() {
  $("#Spinner").show();

  /// add an event to be executed in about 100ms
  setTimeout(function() {
      imageUrl = $("#canvas")[0].toDataURL();
      /// done, optionally call some other function...
  }, 100);

});

This will give the .show() some time to finish and the event for setTimeout will be queued up after it.

You may need/want to alter the value I started with here (100 ms).

There is also an error in the code that does probably not affect anything but it doesn't hurt to get it right -

The argument for toDataURL must be an image type only, ie. image/png , image/jpeg , image/webp etc. The base64 part should not be there (probably came along when you copied the image type from an exisiting data-uri). As PNG is default there is no need to specify it in any case - simply use:

var dataUri = myCanvas.toDataURL(); /// default is image/png, also when it cannot
                                    /// detect a supported type

or

var dataUri = myCanvas.toDataURL('image/png');
var dataUri = myCanvas.toDataURL('image/jpeg');

etc.

I think your problem is very similar to the one described in the following question: innerHTML can't be trusted: Does not always execute synchronously .

Basically, DOM updates are not really "synchronous", which means that your request to display the spinner will happen only once your current code is finished.

You need to keep in mind that javascript execution is single-threaded, threrefore any costly computation will just freeze your UI. Showing a spinner makes sense when doing a long asynchronous operation like an AJAX request but it is useless when doing a blocking synchronous operation like toDataURL because UI has not chance to get updated before it is finished.

If you need to execute long synchronous code then take a look at Web Workers: http://www.html5rocks.com/en/tutorials/workers/basics/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM