如何使用单个功能在画布上绘制多个图像?

时间:2018-12-24 23:25:12

标签: javascript canvas

我正在尝试在HTML Canvas元素上绘制多个图像。

assetData是对象的数组,每个对象包含从数据库中获取的将图像写入画布所需的数据。至关重要的是,assetData可以是任意长度:它可以包含一个图像,也可以包含100个图像。

下面的代码不起作用,因为gfxCtx.drawImage()多次绘制数组中指定的最终图像,而不是每个单独的图像。

for(var x = 0; x < assetData.length; x++) {
  var layer = eval(assetData[x])
  var gfx = new Image
  gfx.src = "images/" + layer.src
  gfx.onload = function() {
    gfxCtx.drawImage(gfx, layer.x, layer.y, layer.w, layer.h)
    compile()
  }
}

compile()处理将图像绘制到画布上

如果要绘制固定数量的图像,我将每个图像分配给一个单独的变量。但是,在这种情况下,我不一定知道要绘制多少张图像,而是想使代码保持简洁。

是否有一个干净,直接的解决方案来解决这个问题?

谢谢!

3 个答案:

答案 0 :(得分:1)

要解决此问题,请考虑在forEach()数组上使用assetData方法,而不要像当前那样使用常规的for循环。

这具有为每次循环迭代创建唯一的“关闭”的优势,从而使您可以根据需要将每个唯一的图像正确地绘制到画布中:

assetData.forEach(function(assetItem) {

  // This function has a unique closure which
  // allows you to draw the current assetItem
  // to the canvas to achieve the desired result
  var layer = eval(assetItem);
  var gfx = new Image();
  gfx.src = "images/" + layer.src;
  gfx.onload = function() {

    gfxCtx.drawImage(gfx, layer.x, layer.y, layer.w, layer.h);
    compile();
  }

});

答案 1 :(得分:1)

这是关于异步代码效果的常见问题解答。稍后调用图像onload处理程序时,它将看到在上一次循环迭代中设置的layergfx的值。这将导致最后一张图像被多次绘制到最后一层的画布区域中。 (如果有时控制台上也没有生成错误,我会感到惊讶。)

最简单的解决方案是使用layer声明gfxlet变量。这使它们成为块作用域,并为每个循环迭代创建一个单独的绑定:回调将查看在其中创建了回调函数对象的迭代的变量值。

有关该主题的更多讨论,请参阅JavaScript closure inside loops – simple practical example

答案 2 :(得分:0)

尝试引用onload事件目标而不是gfx,因为在图像加载时gfx的值可能已更改。

for(var x = 0; x < assetData.length; x++) {
    var layer = eval(assetData[x])
    var gfx = new Image
    gfx.src = "images/" + layer.src
    gfx.onload = function(e) {
       gfxCtx.drawImage(e.target, layer.x, layer.y, layer.w, layer.h)
   compile()
  }
}