【问题标题】:Merge Multiple Canvases and Download as Image合并多个画布并下载为图像
【发布时间】:2015-06-15 14:33:17
【问题描述】:

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

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);

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

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

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

【问题讨论】:

    标签: javascript html canvas html5-canvas todataurl


    【解决方案1】:

    您可能会遇到安全错误,这是由于在画布上绘制来源跨域的图像而导致的。在任何画布上绘制跨域图像将“污染”该画布并禁止context.toDataURL,如果您尝试执行toDataURL,则会引发安全错误。如果将受污染的画布绘制到未受污染的画布上,也会发生同样的“污染”。

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

    以下是您的代码在使用不会引发跨域安全错误的图像时正常工作的示例:

    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>

    满足跨域安全限制

    您可以将图像托管在已经允许跨域访问其图像的服务器上。这就是我在上面的示例中所做的。 Dropbox.com 允许您指定其托管的图像可以绘制到画布上,而不会“污染”该画布。

    您还可以配置您的 S3 存储桶以允许跨域访问您的图像。此链接提供有关如何将响应标头设置为服务器跨域图像的说明:http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

    请注意,在我的示例中,如果您使用的是跨域图像,您还必须在最初在 javascript 中创建图像对象时设置 image.crossOrigin='anonymous' 标志。

    【讨论】:

    • 谢谢。但是有没有办法允许一个图像在外部托管? BottleCanvas 使用存储在本地的图像,而 editorCanvas 使用存储在 S3 存储桶中的图像 - 因为每个用户的图像都不同。
    • 没有办法绕过跨域安全——你必须遵守它。如果“本地存储”是指在您的本地硬盘驱动器上(而不是您服务网站中的目录),那么该图像将“污染”您的画布。 S3 映像可以符合跨域安全限制,但它们并不是开箱即用的。我已经添加到我的答案中,对此进行了更多解释。祝你的项目好运。
    猜你喜欢
    • 2013-01-22
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多