简体   繁体   English

无法在其中保存图像<canvas>

[英]Can't save an image inside <canvas>

I'm still new to this whole canvas things and there's something I have a problem with, namely, saving the content inside the canvas as image. 我对整个画布还是陌生的,我有一个问题,那就是将画布内的内容保存为图像。 Here's my fiddle 这是我的小提琴

 var img = new Image(); img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg'; var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); img.onload = function() { ctx.drawImage(img, 0, 0); img.style.display = 'none'; }; var link = document.createElement('a'); link.innerHTML = 'Save'; link.href = document.getElementById('canvas').toDataURL(); link.addEventListener('click', function(e) { link.download = "imagename.png"; }, false); document.body.appendChild(link); 
 <canvas id="canvas" width="300" height="300"></canvas> 

While the save dialog appears just fine, the saved image is empty, like it doesn't capture the content at all. 尽管保存对话框看起来很好,但是保存的图像是空白的,就像它根本无法捕获内容一样。

Any help is appreciated, moreso if it's accompanied by on how/why my code doesn't work and your code will. 感谢您提供任何帮助,此外,如果附有有关如何/为什么我的代码不起作用,而您的代码将如何起作用的帮助,则更好。 Thanks. 谢谢。

Edit: Forgot to link the fiddle I base my code from here The difference is that that fiddle saves the drawing in the canvas while what I wrote is merely saving a static image from another source. 编辑:忘记链接小提琴,我从这里开始建立我的代码。不同之处在于,小提琴将图形保存在画布中,而我写的只是保存来自其他来源的静态图像。

You need to set image href inside of onload and use img.crossOrigin = "anonymous" just to avoid cross origin error. 您需要在onload内设置image href并使用img.crossOrigin = "anonymous"只是为了避免跨源错误。

 var img = new Image(); img.crossOrigin = "anonymous"; img.src = 'http://farm5.static.flickr.com/4005/4706825697_c0367e6dee_b.jpg'; var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); img.onload = function() { ctx.drawImage(img, 0, 0, 300, 300); link.href = document.getElementById('canvas').toDataURL(); }; var link = document.createElement('a'); link.innerHTML = 'Save'; //link.href = document.getElementById('canvas').toDataURL(); link.addEventListener('click', function(e) { link.download = "imagename.png"; }, false); document.body.appendChild(link); 
 <canvas id="canvas" width="300" height="300"></canvas> 

There are two issues. 有两个问题。

The first is the image's origin. 首先是图像的原点。 On JSFiddle you'll get an Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. 在JSFiddle上,您将获得Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

  • As mentioned in another answer, Base64 encoding the image then setting img.src = 'data:image/jpeg;base64,/...'; 如另一个答案所述,对图像进行Base64编码,然后设置img.src = 'data:image/jpeg;base64,/...'; resolves this problem. 解决了这个问题。
  • Another solution: run a web server locally, and source the image by its location on the server, eg img.src = './rhino.jpg'; 另一种解决方案:在本地运行Web服务器,并根据其在服务器上的位置来获取图像,例如img.src = './rhino.jpg'; .

Even after that's handled, the downloaded image will be "empty," as before. 即使经过处理,下载的图像也将像以前一样为“空”。 This is because of the order of execution of your code. 这是因为代码执行的顺序。 link.href = canvas.toDataURL(); executes before the image's 'load' event fires, so the canvas is empty at the point you're setting the data. 在图像的“加载”事件触发之前执行,因此在设置数据时画布空。

  • Placing that line inside the img.onload function ensures that the link's download data is set only after the image has loaded. 将该行放在img.onload函数中可确保仅在加载图像后才设置链接的下载数据。 This approach is convenient, because it allows for the <a> tag to behave with default behavior once the href attribute is set (eg pointer on hover, underlined text by default). 这种方法很方便,因为一旦设置了href属性(例如,将鼠标悬停在指针上,默认情况下带下划线的文本),它允许<a>标记以默认行为运行。
  • Placing that line, instead, inside the link's 'click' event handler incidentally works, but you lose the default link behavior mentioned above. 而是在链接的“ click”事件处理程序内放置该行,但是您失去了上述的默认链接行为。

Here's an example of the working JS, assuming the image file is on the server: 这是工作JS的示例,假设图像文件在服务器上:

 var img = new Image(); img.src = './rhino.jpg'; var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); var link = document.createElement('a'); link.innerHTML = 'Save'; img.onload = function() { ctx.drawImage(img, 0, 0); img.style.display = 'none'; link.href = canvas.toDataURL(); }; link.addEventListener('click', function(e) { link.download = "imagename.png"; }, false); document.body.appendChild(link); 

And a JSFiddle , using the Base-64 encoded image. 还有一个JSFiddle ,使用Base-64编码的图像。

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

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