html2canvas 下载带有 SVG 背景图像的图像

html2canvas download image with background image on SVG

嗨 html2canvas 和 SVG 大师也许你可以帮助我,我正在尝试从用户在 SVG 区域设置图像的 SVG 下载图像,但是当我使用 html2canvas 生成图像时,背景图像看起来很奇怪并且下载生成的文件,出现错误: “未捕获(承诺)DOMException:无法执行 'toDataURL' 'HTMLCanvasElement': 受污染的画布可能无法导出。"

为了更好的理解,我举了个例子: http://jsfiddle.net/equerol/sodofkcs/5711/

  html2canvas(document.getElementById("svgContainer"), {
    logging: true,
    allowTaint: true,
  }).then(function(canvas) {
    document.body.appendChild(canvas);
    var myImage = canvas.toDataURL("image/png");
    downloadURI("data:" + myImage, "yourImage.png");
  });

谢谢。

我不太明白你的问题。我想你在这里问了两件事(图片看起来很奇怪,由于受到污染 canvas 无法下载)。

对于第一个问题,你应该弄清楚你真正想问的是什么(奇怪是什么意思?你想达到什么目的?...)

对于第二个 (Tainted canvas),您正在处理一个安全问题:

Allowing cross-origin use of images and canvas

以上link深入解释了您面临的问题。

您应该尝试使用 link 中建议的方法之一。

我可以通过在您的 canvas 中使用嵌入式图像数据 URI 轻松解决安全问题,这样它就不会再受到污染。我基本上用 dataURI 替换了你的外部图像 URL。 请尝试找到更适合您问题的解决方案。

Working version of your fiddle (download canvas is possible)

以下是受影响的代码以及我为使其正常工作而替换的代码(已截断):

/* ... */
            <g id="svgPoly4" clip-path="url(#d)" class="droppable">
              <image width="500" height="500" xlink:href="data:image/png;base64,iVBORw0KGgoAAAA....ggg=="></image>
        </g>
/* ... */

更新 1 // 2019-01-08

抱歉,在原来的回答中我应该更清楚你所面临的安全问题。

基本上,您是在尝试获取 SVG 合成中的外国图像 reformatted/redesigned 的屏幕截图。这意味着恶意实体可以使用此技术劫持用户的敏感信息(图像),以防浏览器未阻止它。

您应该真正解决您的问题是从与页面其余部分相同的来源提供嵌入在 SVG 中的图像。如果在某些 reason/use 情况下您需要为作品获取外国图像,这些图像应由您的 back-end.

代理

无论如何,我对您的 fiddle 做了一些调整,现在它可以在 Chrome、Firefox 和 Safari 中使用。 Edge 将无法工作(但考虑到您的初始实施,我猜您还没有尝试过)。

Upgraded jsFiddle version

这个版本突出了你应该do to replace the image in your SVG

注:图片之前已经上传到允许跨源访问资源的服务器(添加Access-Control-Allow-Origin header)

SVG html 作为模板字符串加载,其中数据 URL 将在加载图像时被替换。

图像已加载:

var downloadedImg = new Image;
downloadedImg.crossOrigin = "Anonymous";
downloadedImg.addEventListener("load", imageReceived, false);
downloadedImg.src = "https://i.imgur.com/szhc74z.png";

数据 URL 在模板 SVG 中被替换 html 字符串:

var svg = svgTemplate.replace('${imageUrl}', dataUrl);
document.getElementById('rootSvg').innerHTML = svg;

Safari 的其他解决方法:

看来 html2canvas 及其 "re-renders" SVG 的方式存在某种问题。

为了缓解这种情况,一旦将 SVG 添加到文档中,就会调用 html2canvas 函数。这将 "warm up" "real" 调用的过程。

我的fiddle的目的只是为了证明这个壮举是可以完成的,但是尝试使用back-end代理方法或不同的设计来解决您的问题。