你如何处理html5的画布图像加载异步? [英] How do you deal with html5's canvas image load asynchrony?

查看:751
本文介绍了你如何处理html5的画布图像加载异步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在学习html5的画布。因为图像可能需要一段时间来加载,所以似乎适当的技术是使用 onload 等待图像加载,然后再尝试绘制它。所以:

I've been learning about html5's canvas. Because images can take a while to load, it seems the appropriate technique is to use onload to wait for the image to load before attempting to draw it. So:

<canvas id="fig" width="400" height="400"></canvas>

var fig = document.getElementById('fig1');
var ctx = fig.getContext('2d');

var img = new Image();
img.onload = function() { ctx.drawImage(img, 300, 100); };
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';

然而,在onload函数执行<$ c之前,可能会执行此后的代码$ c> drawImage(),可能导致不良行为:

However, it is likely that code following this gets executed before the onload function can do the drawImage(), possibly causing undesired behavior:

ctx.translate(0,400); ctx.scale(1,-1);   /* switch to lower-left as origin */
/* if onload happens after here, it uses new coordinate system! */
ctx.beginPath();
ctx.moveTo(10, 20);
ctx.lineTo(290, 30);
ctx.stroke();

当然有一些明智的方法来解决这个问题(并在onload函数中做所有事情似乎不合情理)。

Surely there is some sensible way of dealing with this (and doing everything in the onload function seems non-sensible).

========================= =以下编辑========================

========================== EDIT BELOW ========================

以下是对我的代码的更改一个承诺,尽可能简单地说明这个想法。

Here is a change to my code using a single promise to illustrate the idea as simply as I can.

var img = new Image();
var promise = new Promise(                         // make a promise
        function(resolve, reject) {
                img.onload = function() {
                        ctx.drawImage(img, 300, 100);   
                        resolve();     // keep the promise -- lets the "then" proceed
                };      
                img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
        }
);

// .then() waits for the promise to be resolved (see also .catch for rejection)
promise.then( function() {
        ctx.translate(0,400); ctx.scale(1,-1);
        ctx.beginPath();
        ctx.moveTo(10, 20);
        ctx.lineTo(290, 30);
        ctx.stroke();
});


推荐答案

在使用画布之前预先加载图像。将所有图像网址放入一个数组中,循环遍历数组创建新图像,当它们全部加载时,调用一个将启动画布工​​作的函数。

Pre-load your images before working with the canvas. Put all your image urls into an array, loop through the array creating new images, and when they are all loaded call a function that will start your canvas work.

以下代码段使用本机JS 承诺,但如果支持没有本机Promise的旧浏览器可以以类似的方式使用Q或jQuery库

Following snippet uses the native JS Promises, but if supporting older browsers that do not have native Promise you can use Q or jQuery libraries in a similar fashion

var images = ['imageurl.jpg','imageurl2.jpg','imageurl3.jpg'];
var loadedImages = {};
var promiseArray = images.map(function(imgurl){
   var prom = new Promise(function(resolve,reject){
       var img = new Image();
       img.onload = function(){
           loadedImages[imgurl] = img;
           resolve();
       };
       img.src = imgurl;
   });
   return prom;
});

Promise.all(promiseArray).then(imagesLoaded);

function imagesLoaded(){
   //start canvas work.

   //when needing to draw image, access the loaded image in loadedImages
   ctx.drawImage(loadedImages['imageurl.jpg'], 300, 100);
}

这篇关于你如何处理html5的画布图像加载异步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆