将 new Image() 绘制到画布上并使用 canvas.toDataURL()

问题描述 投票:0回答:1
我正在做一个业余项目,试图获得一个对元素进行屏幕截图的按钮。我按照

渲染 HTML 元素到 中的代码将元素渲染到画布中,然后 canvas.toDataURL()

 创建图像。

我收到此错误:未捕获

SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.


我在这里读到了各种帖子,加载图像文件或在本地主机上工作时会出现问题。但是,我在 Netlify 上也遇到了错误,在除 Firefox 之外的所有浏览器中(这是本地预期的情况)。一个建议是将

crossorigin

 属性设置为 
anonymous
,我已经这样做了,但没有效果。

我在几个地方读过,包括

这篇文章,我需要在图像上设置标题。由于它来自 JS 中的new Image()

,我可以安全地为整个网站设置这些标头吗?即使我可以,它能解决问题吗?

我的代码的相关部分:

function renderHtmlToCanvas(canvas, html) { const ctx = canvas.getContext('2d'); const svg = ` <svg xmlns="http://www.w3.org/2000/svg" width="${canvas.width}" height="${canvas.height}"> <foreignObject width="100%" height="100%"> <div xmlns="http://www.w3.org/1999/xhtml">${html}</div> </foreignObject> </svg>`; const svgBlob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' }); const svgObjectUrl = URL.createObjectURL(svgBlob); const tempImage = new Image(); tempImage.crossOrigin = 'anonymous'; tempImage.addEventListener('load', () => { ctx.drawImage(tempImage, 0, 0); canvasToImage(canvas); URL.revokeObjectURL(svgObjectUrl); }); tempImage.src = svgObjectUrl; } // Convert the canvas to an image function canvasToImage(canvas) { const image = new Image(); const screenshotData = canvas.toDataURL('image/webp'); } renderHtmlToCanvas(canvas, html);
    
javascript canvas cors
1个回答
0
投票
我稍微改变了你的方法并让这个工作(几乎完成)。

// This function takes any DOMDocumentElement as a first parameter. // And return a Data URL of its generated image. function RenderElement ( Element ) { // Take the measures of the given Element. const Measures = Element.getBoundingClientRect(); // The canvas does not need to exist in your document body. const CanvasElement = document.createElement('canvas'); { // The canvas is adjusted here. CanvasElement.width = Measures.width; CanvasElement.height = Measures.height; } const Context = CanvasElement.getContext('2d'); // Slightly changed SVG... const ImageSVG = ` <svg xmlns="http://www.w3.org/2000/svg" width="${CanvasElement.width}" height="${CanvasElement.height}"> <!-- YOU SHOULD INCLUDE ALL CSS RULES DIRECTLY HERE --> <foreignObject width="100%" height="100%"> <div xmlns="http://www.w3.org/1999/xhtml"> ${Element.outerHTML} </div> </foreignObject> </svg> `; // The image also does not need to exist in your document body. const ImageElement = document.createElement('img'); { // The svg image source is already converted to Data URL (Base64). ImageElement.src = `data:image/svg+xml;base64,${btoa(ImageSVG)}`; } Context.drawImage(ImageElement, 0, 0); // Get the Data URL directly from the virtual canvas. const ImageSRC = CanvasElement.toDataURL('image/webp'); return ImageSRC; } // Just creating a new image with the Generated image of the element. const NewImg = document.createElement('img'); { NewImg.src = RenderElement(document.getElementById('MyContent')); } // Appending the NewImg to the document. document.body.appendChild(NewImg); // Logging the NewImg.src to the console console.log(NewImg.src);
<div id="MyContent">
  <button>I do nothing</button>
  <div>Hello World!</div>
</div>
<hr />
<div>
  Generated image of what is above the hr above is shown below horizontal ruler below:
</div>
<hr />

运行该代码片段以查看其实际效果。如果第一次

Run

 单击不起作用,请再次单击。

重要: 此函数不会将任何 CSS 导入到 SVG 中,这实际上会重新渲染您的元素。因此,您必须确保 CSS 规则加载到您的 SVG 内容中。

© www.soinside.com 2019 - 2024. All rights reserved.