合并多个画布并下载为图像

Merge Multiple Canvases and Download as Image

我正在尝试将两个 HTML canvas 合并为一个 canvas,然后将其作为图像下载。我的代码如下:

function downloadCanvas() {
    var bottleCanvas = document.getElementById('bottleCanvas');
    var designCanvas = document.getElementById('editorCanvas');

    var bottleContext = bottleCanvas.getContext('2d');
    bottleContext.drawImage(designCanvas, 69, 50);

    var dataURL = bottleCanvas.toDataURL("image/png");
    var link = document.createElement('a');
    link.download = "bottle-design.png";
    link.href = bottleCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
    link.click();
}

我的问题似乎是以下一行:

bottleContext.drawImage(designCanvas, 69, 50);

这应该将一个 canvas 的内容绘制到另一个上,它确实这样做了,但随后阻止了代码的后半部分 运行 和下载图像。当我删除此特定行时,下载功能工作正常,但不幸的是只下载了 canvases.

之一

因此我的问题是:我在这里做错了什么?或者我如何合并两个 HTML canvases 然后将其下载为图像。

(另外请注意,我上面的下载代码仅在 Chrome 中运行良好 - 在其他浏览器中我无法设置文件名和文件扩展名。)

您可能遇到了一个安全错误,这是因为将来源为 cross-domain 的图像绘制到您的 canvas 上。在任何 canvas 上绘制 cross-domain 图像将 "taint" canvas 并且不允许 context.toDataURL 并在您尝试执行 toDataURL 时引发安全错误。如果将受污染的 canvas 绘制到 non-contaminated canvas.

上,也会发生同样的 "tainting"

解决方法是确保您在 canvas 上绘制的所有图像都来自与您的网页相同的域。

这是您的代码在使用未引发 cross-domain 安全错误的图像时正常工作的示例:

var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/fish.jpg";
function start(){

  var bottleCanvas = document.getElementById('bottleCanvas');
  var designCanvas = document.getElementById('editorCanvas');
  var ctxb=bottleCanvas.getContext('2d');
  var ctxd=editorCanvas.getContext('2d');

  ctxb.drawImage(img,0,0);
  ctxd.fillRect(50,50,50,50);

  downloadCanvas();
}

function downloadCanvas() {
  var bottleCanvas = document.getElementById('bottleCanvas');
  var designCanvas = document.getElementById('editorCanvas');

  var bottleContext = bottleCanvas.getContext('2d');
  bottleContext.drawImage(designCanvas, 69, 50);

  var dataURL = bottleCanvas.toDataURL("image/png");
  var link = document.createElement('a');
  link.download = "bottle-design.png";
  link.href = bottleCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
  link.click();
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<canvas id="bottleCanvas" width=300 height=300></canvas>
<canvas id="editorCanvas" width=300 height=300></canvas>

满足cross-origin安全限制

您可以将图像托管在已经允许 cross-origin 访问其图像的服务器上。这就是我在上面的示例中所做的。 Dropbox.com 允许您指定它承载的图像可以绘制到 canvas 而不是 "tainting" canvas.

您还可以配置 S3 存储桶以允许 cross-origin 访问您的图像。此 link 提供了有关如何设置对服务器 cross-origin 图像的响应 headers 的说明:http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

请注意,在我的示例中,如果您使用 cross-origin 图像,则在 [=63] 中最初创建图像 object 时,还必须设置 image.crossOrigin='anonymous' 标志=].