javascript 在 canvas 上绘制时承诺/异步/等待行为
javascript promis / async / await behaviour when drawing on canvas
这是我的问题:
我有 class 个由一定数量的属性和方法定义的对象,其中:
- 恢复为文本或图像的“类型”属性
- 一个 drawObject 方法,如果它是图像,它将在 canvas 上绘制(canvas drawImage 函数)对象,如果它是一个文本(canvas fillText 函数)。
在 canvas 上,我可以 draw/writ 存储在数组中的任意数量的对象。
我的问题是我试图以给定的顺序绘制这些对象,以便重叠与数组中对象的顺序一致。
为此,我按以下方式解析数组中的所有对象:
function drawer(obj) {
return new Promise((resolve) => {
let objToDraw = obj.drawObject();
resolve(objToDraw);
})
}
async function drawObjects() {
for (const obj of pageObjects) {
await drawer(obj);
}
}
drawObjects();
我的预期是,如果 drawObject 函数已经完成其工作,包括 canvas 上的绘图,则“for of”循环只会从一个迭代转到下一个迭代。
但是所有“文本”对象总是在图像之前绘制,甚至图像有时也会以意想不到的顺序绘制。
以下是 drawObject、wrapText(由 drawObject 调用)方法:
drawObject() {
if (this.type == "image")
{
var drawTheImg = new Image();
drawTheImg.src = this.destImg
drawTheImg.onload = function () {
showCtx.save();
showCtx.drawImage(drawTheImg, this.sx, this.sy, swidth, sheight, this.dx, this.dy, this.dwidth, this.dheight);
showAlbumCtx.restore();
}.bind(this)
} else {
showAlbumCtx.save();
showAlbumCtx.fillStyle = this.fontColor;
showAlbumCtx.textBaseline = "top";
this.wrapText((this.dy + this.textLineHeight));
showAlbumCtx.restore();
}
}
wrapText(y) {
var words = this.containedText.split(' ');
var line = '';
showAlbumCtx.save();
if (this.txtJustification === "right") {
var x = (this.dx + this.textPadding) + (this.dwidth - this.textPadding);
} else if (this.txtJustification === "center") {
var x = (this.dx + this.textPadding) + ((this.dwidth - this.textPadding) / 2);
} else {
x = (this.dx + this.textPadding);
}
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = showAlbumCtx.measureText(testLine);
var testWidth = metrics.width;
if (n > 0 && words[n - 1].match(/\n/g)) {
showAlbumCtx.fillText(line, x, y);
line = words[n] + ' ';
y += this.textLineHeight;
} else if (testWidth > this.textMaxWidth && n > 0) {
showAlbumCtx.fillText(line, x, y);
line = words[n] + ' ';
y += this.textLineHeight;
} else {
line = testLine;
}
}
showAlbumCtx.fillText(line, x, y);
showAlbumCtx.restore();
}
感谢您提供的任何建议
如果有人需要答案,我的问题已通过使用 Bergi 的建议并使 drawObject return 成为 Promise 得到解决。
这是我的问题: 我有 class 个由一定数量的属性和方法定义的对象,其中:
- 恢复为文本或图像的“类型”属性
- 一个 drawObject 方法,如果它是图像,它将在 canvas 上绘制(canvas drawImage 函数)对象,如果它是一个文本(canvas fillText 函数)。
在 canvas 上,我可以 draw/writ 存储在数组中的任意数量的对象。
我的问题是我试图以给定的顺序绘制这些对象,以便重叠与数组中对象的顺序一致。
为此,我按以下方式解析数组中的所有对象:
function drawer(obj) {
return new Promise((resolve) => {
let objToDraw = obj.drawObject();
resolve(objToDraw);
})
}
async function drawObjects() {
for (const obj of pageObjects) {
await drawer(obj);
}
}
drawObjects();
我的预期是,如果 drawObject 函数已经完成其工作,包括 canvas 上的绘图,则“for of”循环只会从一个迭代转到下一个迭代。 但是所有“文本”对象总是在图像之前绘制,甚至图像有时也会以意想不到的顺序绘制。
以下是 drawObject、wrapText(由 drawObject 调用)方法:
drawObject() {
if (this.type == "image")
{
var drawTheImg = new Image();
drawTheImg.src = this.destImg
drawTheImg.onload = function () {
showCtx.save();
showCtx.drawImage(drawTheImg, this.sx, this.sy, swidth, sheight, this.dx, this.dy, this.dwidth, this.dheight);
showAlbumCtx.restore();
}.bind(this)
} else {
showAlbumCtx.save();
showAlbumCtx.fillStyle = this.fontColor;
showAlbumCtx.textBaseline = "top";
this.wrapText((this.dy + this.textLineHeight));
showAlbumCtx.restore();
}
}
wrapText(y) {
var words = this.containedText.split(' ');
var line = '';
showAlbumCtx.save();
if (this.txtJustification === "right") {
var x = (this.dx + this.textPadding) + (this.dwidth - this.textPadding);
} else if (this.txtJustification === "center") {
var x = (this.dx + this.textPadding) + ((this.dwidth - this.textPadding) / 2);
} else {
x = (this.dx + this.textPadding);
}
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = showAlbumCtx.measureText(testLine);
var testWidth = metrics.width;
if (n > 0 && words[n - 1].match(/\n/g)) {
showAlbumCtx.fillText(line, x, y);
line = words[n] + ' ';
y += this.textLineHeight;
} else if (testWidth > this.textMaxWidth && n > 0) {
showAlbumCtx.fillText(line, x, y);
line = words[n] + ' ';
y += this.textLineHeight;
} else {
line = testLine;
}
}
showAlbumCtx.fillText(line, x, y);
showAlbumCtx.restore();
}
感谢您提供的任何建议
如果有人需要答案,我的问题已通过使用 Bergi 的建议并使 drawObject return 成为 Promise 得到解决。