简体   繁体   English

html2canvas在SVG上下载带有背景图片的图片

[英]html2canvas download image with background image on SVG

Hi html2canvas & SVG masters maybe you can help me, im trying to download an image from a SVG where the user sets images on the SVG areas, but when i generate the image with html2canvas the background images appears strange and to download the generated file, i get an error: "Uncaught (in promise) DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported." 嗨html2canvas和SVG大师,您可能会帮助我,我试图从SVG下载图像,用户在SVG区域上设置了图像,但是当我使用html2canvas生成图像时,背景图像显得奇怪并要下载生成的文件,我收到一个错误:“未捕获(承诺)DOMException:无法在'HTMLCanvasElement'上执行'toDataURL':可能无法导出污染的画布。”

I made an example to better understanding: http://jsfiddle.net/equerol/sodofkcs/5711/ 我举了一个例子来更好地理解: 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");
  });

Thanks. 谢谢。

I don't really understand your question. 我不太了解您的问题。 I think you're asking two things here (Images appear strange, download is not possible due to tainted canvas). 我想您在这里问了两件事(图片看起来很奇怪,由于画布变脏而无法下载)。

For the first question you should clarify what you're really asking (What does strange mean? what do you want to achieve?...) 对于第一个问题,您应该弄清楚您真正要问的是什么(奇怪是什么意思?您想要实现什么?...)

For the second (Tainted canvas), you are dealing with a security problem: 对于第二个(污染画布),您正在处理一个安全问题:

Allowing cross-origin use of images and canvas 允许跨域使用图像和画布

The above link explains in depth the problem you are facing. 上面的链接深入说明了您面临的问题。

You should try to use one of the approaches suggested in the link. 您应该尝试使用链接中建议的方法之一。

I can easily overcome the security problem by using an embedded image data URI within your canvas so that it's no longer tainted. 我可以通过在画布中使用嵌入的图像数据URI来轻松解决安全性问题,使其不再被污染。 I basically replaced your external image URL with a dataURI. 我基本上用dataURI替换了您的外部图像URL。 Please try to find a better solution that suits your problem. 请尝试找到适合您问题的更好解决方案。

Working version of your fiddle (download canvas is possible) 小提琴的工作版本(可以下载画布)

Here is the affected code and what I replaced to make it work (truncated): 这是受影响的代码,以及我替换掉的代码以使其正常工作(被截断):

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

Update 1 // 2019-01-08 更新1 // 2019-01-08

Sorry, in the original answer I should have been more clear about the security issue you are facing. 抱歉,在原始答案中,我应该更加清楚您所面临的安全问题。

Basically you are trying to get a screenshot of a foreign image reformatted/redesigned within an SVG composition. 基本上,您正在尝试获取在SVG合成中重新格式化/重新设计的外国图像的屏幕截图。 This means that a malicious entity could use this technique to hijack sensitive information (images) from a user in case the browser didn't prevent it. 这意味着恶意实体可以使用此技术从用户劫持敏感信息(图像),以防浏览器无法阻止它。

What you should really do to overcome your problem is serve the images embedded in the SVG from the same origin as the rest of the page. 真正解决您的问题,您真正应该做的是从与页面其余部分相同的来源提供嵌入SVG的图像。 If for some reason/use case you require to fetch foreign images for the composition, these images should be proxied by your back-end. 如果出于某些原因/用例需要获取构图的外来图像,则这些图像应由后端代理。

Anyway, I've tweaked a little more your fiddle and now it's usable from Chrome, Firefox and Safari. 无论如何,我已经调整了一些小提琴,现在可以在Chrome,Firefox和Safari中使用。 Edge won't work (but given your initial implementation I guess you haven't tried it yet). Edge无法正常工作(但是考虑到您最初的实现方式,我想您尚未尝试过)。

Upgraded jsFiddle version 升级的jsFiddle版本

This version highlights what you should do to replace the image in your SVG . 此版本突出显示了您应该如何替换SVG中的映像

Note: The image has been previously uploaded to a server that allows cross origin access to resources (it adds Access-Control-Allow-Origin header) 注意:图像先前已上传到允许跨源访问资源的服务器(它添加了Access-Control-Allow-Origin标头)

The SVG html is loaded as a template string where the data URL will be replaced when the image is loaded. SVG html作为模板字符串加载,在加载图像时将替换数据URL。

Image is loaded: 图片已加载:

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

Data URL is replaced in template SVG html string: 在模板SVG html字符串中替换了数据URL:

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

Additional workaround for Safari: Safari的其他解决方法:

It appears that there's some kind of issue with html2canvas and the way it "re-renders" the SVG. 似乎html2canvas及其“重新渲染” SVG的方式存在某种问题。

To mitigate this, html2canvas function is invoked once the SVG is added to the document. 为了减轻这种情况,将SVG添加到文档后,将调用html2canvas函数。 This will "warm up" the procedure for the "real" invocations. 这将“预热”“真实”调用的过程。

The intention of my fiddle is just to demonstrate that the feat can be accomplished, but please try to use the back-end proxy approach or a different design to solve your problem. 我的小提琴的目的只是为了证明可以实现这一壮举,但是尝试使用后端代理方法或其他设计来解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM