javascript - 画布绘图:等待图像以递归方法加载
问题描述
我正在实现一个递归方法,该方法采用一组图像并将它们绘制到画布中:
async drawImages(ctx, images): Promise<any> {
const img = images.shift();
const imgToDraw = new Image();
imgToDraw.src = img.src;
imgToDraw.onload = () => {
ctx.drawImage(imgToDraw, img.x, img.y, img.w, img.h);
if (images.length > 0) {
this.drawImages(ctx, images);
} else {
console.log("I - Processing");
return Promise.resolve();
}
}
}
在这个方法的执行结束时,我需要检索画布的 DataURL,我这样做是这样的:
someCallingMethod() {
//...
await this.drawImages(ctx, images);
console.log("II - Finished");
console.log(canvas.toDataURL());
}
我面临的问题是 await 不适用于该drawImages
方法。执行此代码时,我总是在"II - Finished"
日志之前获取日志"I - Processing"
,因此canvas.toDataURL()
从不包含应该绘制到画布上的图像。
谢谢
解决方案
您需要同步返回 Promise。
在这里,您将在异步onload
事件处理程序中返回它。
所以drawImages
不会返回 Promise 但未定义。
此外,您将希望返回drawImages
每次的下一次迭代,以便您的外部await
等待所有这些 Promise:
const obj = {
async drawImages(ctx, images) {
// return a Promise synchronously
return new Promise((resolve, reject) => {
const img = images.shift();
const imgToDraw = new Image();
imgToDraw.src = img.src;
imgToDraw.onload = () => {
ctx.drawImage(imgToDraw, img.x, img.y, img.w, img.h);
if (images.length > 0) {
// resolve with next iteration so we can await all
resolve(this.drawImages(ctx, images));
} else {
console.log("I - Processing");
// done
resolve();
}
};
imgToDraw.onerror = reject;
});
}
};
(async () => {
const images = [];
// picsum.photos doesn't fill all the indexes...
const urls = ["01", "02", "03", "04", "05", "06", "10", "11", "12", "13"];
const s = 50; // image size
for(let i=0; i<10; i++) {
images.push( {
src: `https://picsum.photos/${s}/${s}?image=10` + urls[i],
x: (i%5)*s,
y: Math.floor(i/5)*s,
w: s,
h: s
});
}
const ctx = canvas.getContext('2d');
await obj.drawImages(ctx, images);
// fill a green rect over to show we are able to await it
ctx.fillStyle = 'rgba(0,255,0, 0.2)';
ctx.fillRect(0,0,canvas.width,canvas.height);
console.log("all done");
})();
<canvas id="canvas" width="250" height="100"></canvas>
推荐阅读
- configuration - 向操作系统添加或删除一些功能?
- react-native - Netinfo 总是返回 true React Native
- spring-boot - Spring boot,多个@EventListener(ApplicationReadyEvent.class)时如何指定顺序
- python - 我试图删除列表中的标点符号,但它有问题 TypeError: 'float' object is not iterable
- apache-spark - 如何使用 Apache Spark 并行读写两个 DataFrame
- android - 如何在 Android 中处理 Print Job 事件?
- sql - SAS PROC SQL SELECT INTO 宏创建的动态范围
- excel - Power Query (M) _ 动态更新 List.Sum 函数的列列表
- android - 如何修复错误 - 无法解析方法 'subscribe(anonymous rx.functions.Action1
) - android - Glide Transformation 内存泄漏