How do you deal with html5#39;s canvas image load asynchrony?(如何处理 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 函数执行 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();
});
推荐答案
在使用画布之前预加载图像.将你所有的图片 url 放入一个数组中,通过数组循环创建新图片,当它们全部加载完毕后,调用一个函数来启动你的画布工作.
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 Promises,但如果支持没有原生 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 的画布图像加载异步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何处理 html5 的画布图像加载异步?
基础教程推荐
- 自定义 XMLHttpRequest.prototype.open 2022-01-01
- 如何使用TypeScrip将固定承诺数组中的项设置为可选 2022-01-01
- Electron 将 Node.js 和 Chromium 上下文结合起来意味着 2022-01-01
- Vue 3 – <过渡>渲染不能动画的非元素根节点 2022-01-01
- html表格如何通过更改悬停边框来突出显示列? 2022-01-01
- 我可以在浏览器中与Babel一起使用ES模块,而不捆绑我的代码吗? 2022-01-01
- Chart.js 在线性图表上拖动点 2022-01-01
- 如何使用JIT在顺风css中使用布局变体? 2022-01-01
- 用于 Twitter 小部件宽度的 HTML/CSS 2022-01-01
- 直接将值设置为滑块 2022-01-01