将HTML Canvas捕获为gif / jpg / png / pdf吗?


719

是否可以捕获或打印html画布中显示为图像或pdf的内容?

我想通过画布生成图像,并能够从该图像生成png。





1
您可能会发现canvas2image库对此有用:github.com/hongru/canvas2image
noego

Answers:


737

哎呀。原始答案是针对类似问题的。对此进行了修订:

var canvas = document.getElementById("mycanvas");
var img    = canvas.toDataURL("image/png");

使用IMG中的值,您可以将其写为新图像,如下所示:

document.write('<img src="'+img+'"/>');

15
还有一个问题,如何将在此标签中获得的图像保存到服务器。任何猜测吗?
Surya

7
但是,如果我使用var img = canvas.toDataURL(“ image / jpeg”); 正在将背景显示为全黑。如何纠正这一问题
gauti 2013年

181
哦,拜托 我在2009年回答了这个问题。您期望什么?
2014年

35
@donohoe实际上您在2010年8月回答了问题:)
尼克

13
这样做会占用更少的内存var img = new Image(); img.src = canvas.toDataURL(); document.body.appendChild(img);。该document.write代码使得数据URL,他们制作的HTML字符串,然后把该字符串的一个副本,在DOM,浏览器则必须解析HTML字符串,把另一份图像元素上,然后再分析它打开将数据URL转换为图像数据,然后最终可以显示图像。对于屏幕大小的图像,它需要大量的内存/复制/解析。只是一个建议
gman

116

HTML5提供了Canvas.toDataURL(mimetype),可在Opera,Firefox和Safari 4 beta中实现。但是,存在许多安全限制(主要与将其他来源的内容绘制到画布上有关)。

因此,您不需要其他库。

例如

 <canvas id=canvas width=200 height=200></canvas>
 <script>
      window.onload = function() {
          var canvas = document.getElementById("canvas");
          var context = canvas.getContext("2d");
          context.fillStyle = "green";
          context.fillRect(50, 50, 100, 100);
          // no argument defaults to image/png; image/jpeg, etc also work on some
          // implementations -- image/png is the only one that must be supported per spec.
          window.location = canvas.toDataURL("image/png");
      }
 </script>

从理论上讲,这应该创建然后导航到中间带有绿色正方形的图像,但是我尚未进行测试。


2
图像将保存到的位置。在我当地的位置?
chinna_82

5
该图像将在您的浏览器中显示为图像。然后,您可以将其保存到磁盘或其他任何内容。这是一个快速且肮脏的通用“ Canvas2PNG”书签,它将页面中的第一个画布转换为PNG并将其显示在浏览器中的新窗口中:javascript:void(window.open().location = document.getElementsByTagName("canvas")[0].toDataURL("image/png"))
Kai Carver 2014年

如果图像只有几MB,请准备使您的浏览器崩溃(我之前在FireFox中这样做)。
jahu 2015年

1
如何修改它以呈现多个图像?
心理学家,2015年

数据URI的最大长度,因此可以放入数据url的图像大小有上限。
JuhaSyrjälä18年

44

我以为我会扩大此问题的范围,并提供一些有关此事的有用提示。

为了使画布作为图像,您应该执行以下操作:

var canvas = document.getElementById("mycanvas");
var image = canvas.toDataURL("image/png");

您可以使用它来将图像写入页面:

document.write('<img src="'+image+'"/>');

其中“ image / png”是mime类型(png是唯一必须支持的类型)。如果您想要一组受支持的类型,则可以按照以下方式进行操作:

var imageMimes = ['image/png', 'image/bmp', 'image/gif', 'image/jpeg', 'image/tiff']; //Extend as necessary 
var acceptedMimes = new Array();
for(i = 0; i < imageMimes.length; i++) {
    if(canvas.toDataURL(imageMimes[i]).search(imageMimes[i])>=0) {
        acceptedMimes[acceptedMimes.length] = imageMimes[i];
    }
}

您只需要在每个页面上运行一次-它永远不会在页面的生命周期内发生变化。

如果希望让用户下载文件保存后的文件,则可以执行以下操作:

var canvas = document.getElementById("mycanvas");
var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); //Convert image to 'octet-stream' (Just a download, really)
window.location.href = image;

如果您将其与其他MIME类型一起使用,请确保更改image / png的两个实例,但不要更改image / octet-stream。还值得一提的是,如果在渲染画布时使用任何跨域资源,则在尝试使用toDataUrl方法时会遇到安全错误。


1
使用您下载文件的解决方案时,我必须选择我要使用的软件,这有点不方便。是否有办法在下载后将MIME替换为png?
2013年

1
@ So4ne我认为不是,它必须是图像/八位字节流,以提示用户进行下载。如果您摆脱了这一行,最终将导致页面重定向到图像。不过,我很想知道是否有人知道如何做到这一点。
meiamsome

2
在<a>链接上使用target =“ _ blank”并使用.click(),它也应该可以触发下载(使用FF data-url和text / csv和text / plain的download =“ filename”测试)
Ax3l

这很棒。谢谢!但是,如果我想保存到服务器而不是本地怎么办?表单文件输入会接受img src作为可上载的内容吗?
首席炼金术士2015年

哎呀。刚找到答案。留下的情况下别人前面的问题是寻找以及stackoverflow.com/questions/13198131/...
首席炼金

34
function exportCanvasAsPNG(id, fileName) {

    var canvasElement = document.getElementById(id);

    var MIME_TYPE = "image/png";

    var imgURL = canvasElement.toDataURL(MIME_TYPE);

    var dlLink = document.createElement('a');
    dlLink.download = fileName;
    dlLink.href = imgURL;
    dlLink.dataset.downloadurl = [MIME_TYPE, dlLink.download, dlLink.href].join(':');

    document.body.appendChild(dlLink);
    dlLink.click();
    document.body.removeChild(dlLink);
}

保存的文件保持.svg格式。如何将其另存为png?
nullpointer '16

这是一个很好的解决方案,除了它可能无法在IE上运行。收到错误“传递给系统调用的数据区域太小”
Jose Cherian

在Chrome中显示“网络错误”,而在Firefox中则显示良好。(在Linux上)
Ecker00'1

20

我会使用“ wkhtmltopdf ”。效果很好。它使用webkit引擎(用于Chrome,Safari等),并且非常易于使用:

wkhtmltopdf stackoverflow.com/questions/923885/ this_question.pdf

而已!

尝试一下


1
我也在wkhtmltopdf阵营中。我们一直在使用它进行存档及其惊人的工作。
Daniel Szabo 2012年

如何在需要登录信息的页面中使用WKHTMLtoPDF?我正在使用Jsreport转换为PDF,但是我使用HTML2Canvas捕获了我的内容,将Canvas作为参数发送给JSreport时遇到了问题
khaled Dehia


15

如果您通过服务器下载文件,则有一些帮助(通过这种方式,您可以命名/转换/后处理/等文件):

-使用发布数据 toDataURL

-设置标题

$filename = "test.jpg"; //or png
header('Content-Description: File Transfer');
if($msie = !strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false)      
  header("Content-type: application/force-download");else       
  header("Content-type: application/octet-stream"); 
header("Content-Disposition: attachment; filename=\"$filename\"");   
header("Content-Transfer-Encoding: binary"); 
header("Expires: 0"); header("Cache-Control: must-revalidate"); 
header("Pragma: public");

-创建图像

$data = $_POST['data'];
$img = imagecreatefromstring(base64_decode(substr($data,strpos($data,',')+1)));

-将图像导出为JPEG

$width = imagesx($img);
$height = imagesy($img);
$output = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($output,  255, 255, 255);
imagefilledrectangle($output, 0, 0, $width, $height, $white);
imagecopy($output, $img, 0, 0, 0, 0, $width, $height);
imagejpeg($output);
exit();

-或作为透明PNG

imagesavealpha($img, true);
imagepng($img);
die($img);

9

另一个有趣的解决方案是PhantomJS。这是一个无头WebKit,可使用JavaScript或CoffeeScript编写脚本。

用例之一是屏幕捕获:您可以以编程方式捕获Web内容,包括SVG和Canvas,和/或使用缩略图预览创建网站截图。

最好的入口点是屏幕捕获 Wiki页面。

这是一个极地时钟的好例子(来自RaphaelJS):

>phantomjs rasterize.js http://raphaeljs.com/polar-clock.html clock.png

您想将页面呈现为PDF吗?

> phantomjs rasterize.js 'http://en.wikipedia.org/w/index.php?title=Jakarta&printable=yes' jakarta.pdf

2
+1:PhantomJS是简单,文档完善且经过深思熟虑的系统,非常适合此工作。它不仅允许抓取画布,还提供了更多功能-例如,您可以在抓取之前(通过JS)修改页面或页面的一部分,使它看起来像您想要的样子。完善!
约翰多多

1
PhantomJs现在已过时
-Merc

3

如果您使用的是很多人都使用的jQuery,则可以像这样实现已接受的答案:

var canvas = $("#mycanvas")[0];
var img = canvas.toDataURL("image/png");

$("#elememt-to-write-to").html('<img src="'+img+'"/>');

12
请注意,这里jQuery 的唯一用法是选择画布。.toDataURL是本地JS。
j6m8 2014年

我保存的问题有人可以帮我看看这个链接:stackoverflow.com/questions/25131763/...
拉梅什小号

2
纯粹的(100%)jQuery解决方案如下:$('<img>').attr('src',$('#mycanvas')[0].toDataURL('image/png')).appendTo($('#element-to-write-to').empty());恰好一行。
Naeel Maqsudov,2015年

1

您可以使用jspdf将画布捕获为图像或pdf,如下所示:

var imgData = canvas.toDataURL('image/png');              
var doc = new jsPDF('p', 'mm');
doc.addImage(imgData, 'PNG', 10, 10);
doc.save('sample-file.pdf');

更多信息:https//github.com/MrRio/jsPDF


1

这是另一种方式,没有字符串,尽管我真的不知道它是否更快。而不是toDataURL(如此处所有问题所建议的)。在我的情况下,由于我需要一个数组缓冲区或视图,因此想阻止dataUrl / base64。因此,HTMLCanvasElement中的另一个方法是toBlob。(TypeScript函数):

    export function canvasToArrayBuffer(canvas: HTMLCanvasElement, mime: string): Promise<ArrayBuffer> {
  return new Promise((resolve, reject) => canvas.toBlob(async (d) => {
    if (d) {
      const r = new FileReader();
      r.addEventListener('loadend', e => {
        const ab = r.result;
        if (ab) {
          resolve(ab as ArrayBuffer);
        }
        else {
           reject(new Error('Expected FileReader result'));
        }
      }); r.addEventListener('error', e => {
        reject(e)
      });
      r.readAsArrayBuffer(d);
    }
    else {
      reject(new Error('Expected toBlob() to be defined'));
    }
  }, mime));
}

Blob的另一个优点是,您可以创建ObjectUrl来将数据表示为文件,类似于HTMLInputFile的“文件”成员。更多信息:

https://developer.mozilla.org/es/docs/Web/API/HTMLCanvasElement/toBlob


-1

在某些版本的Chrome上,您可以:

  1. 使用绘制图像功能 ctx.drawImage(image1, 0, 0, w, h);
  2. 右键单击画布
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.