如何将多个图像绘制到单个画布上?

Posted

技术标签:

【中文标题】如何将多个图像绘制到单个画布上?【英文标题】:How to draw multiple images to a single canvas? 【发布时间】:2021-12-23 09:01:29 【问题描述】:

我正在制作一个网站,让用户可以绘制草图并指定他们的位置和大小;然后,我将它们保存到数据库中。在不同的路线中,我想加载这些图像并将它们显示在单个画布上。

我为此使用了drawImage 函数,但是会发生第二个图像被绘制在第一个图像上的情况。就像下图中circletriangle 的两个草图:

这是我在画布上绘制图像的方法:

var canvas = document.getElementById("paint");    
var ctx = canvas.getContext("2d");
function loadImages(data, targetX, targetY, targetWidth, targetHeight) 

    data = data.replace(/'/g, '"');
    targetX = targetX.replace(/'/g, '"');
    targetY = targetY.replace(/'/g, '"');
    targetWidth = targetWidth.replace(/'/g, '"');
    targetHeight = targetHeight.replace(/'/g, '"');

    data = JSON.parse(data);
    targetX = JSON.parse(targetX);
    targetY = JSON.parse(targetY);
    targetWidth = JSON.parse(targetWidth);
    targetHeight = JSON.parse(targetHeight);

    for(var i = 0; i < data.length; i++) 
        var img = new Image();
        var tx = parseInt(targetX[i]);
        var ty = parseInt(targetY[i]);
        var tw = parseInt(targetWidth[i]);
        var th = parseInt(targetHeight[i]);
        img.src = data[i];
        img.onload = function() 
            ctx.drawImage(this, tx, ty, tw, th);
        ;

        
    


此处的字符串格式化将从数据库(通过 Flask)获取的数据转换为 javascript 数组。我在imgtxtytwth 等所有变量上都使用了console.log(),它们都有所需的值,但仍然在画布上,它们没有正确绘制所以我无法缩小问题的范围。

这是我在 html 文件中调用函数的方式:

% block content %
% if files %

<button id="show" onclick="loadImages(` data `, ` targetX `, ` targetY `, ` sizeX `, ` sizeY `)">View</button>

<canvas id="paint"   style="border: 5px solid #000000;"></canvas>
% endif %
    
<script src="  url_for('static', filename='edit.js') "></script>

% endblock %

【问题讨论】:

【参考方案1】:

您正在同步循环中执行异步操作。试试这个..

var canvas = document.getElementById("paint");
var ctx = canvas.getContext("2d");

async function loadImages(data, targetX, targetY, targetWidth, targetHeight) 
  var images = ;
  data = data.replace(/'/g, '"');
  targetX = targetX.replace(/'/g, '"');
  targetY = targetY.replace(/'/g, '"');
  targetWidth = targetWidth.replace(/'/g, '"');
  targetHeight = targetHeight.replace(/'/g, '"');

  data = JSON.parse(data);
  targetX = JSON.parse(targetX);
  targetY = JSON.parse(targetY);
  targetWidth = JSON.parse(targetWidth);
  targetHeight = JSON.parse(targetHeight);

  for (var i = 0; i < data.length; i++) 
    var tx = parseInt(targetX[i]);
    var ty = parseInt(targetY[i]);
    var tw = parseInt(targetWidth[i]);
    var th = parseInt(targetHeight[i]);
    var img = await loadImage(data[i]);
    ctx.drawImage(img, tx, ty, tw, th);
  



function loadImage(src)
  return new Promise(done=>
    var img = new Image();
    img.src = src;
    img.onload = function() 
      done(img);
    ;
  );

【讨论】:

以上是关于如何将多个图像绘制到单个画布上?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 html 5 画布上旋转单个对象?

如何将内联 svg(在 DOM 中)绘制到画布上?

我们如何在 html5 画布上绘制调整大小的图像?

将图片绘制到画布上:imagecopy()

绘制后如何下载不同的html画布?

如何在 Flutter 的画布上的路径内绘制图案?