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

Par*_*and 684 javascript html5 png export canvas

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

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

don*_*hoe 706

哎呀.原始答案是针对类似问题的.这已被修改:

var canvas = document.getElementById("mycanvas");
var img    = canvas.toDataURL("image/png");
Run Code Online (Sandbox Code Playgroud)

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

document.write('<img src="'+img+'"/>');
Run Code Online (Sandbox Code Playgroud)

  • 哦,来吧.我在2009年回答了这个问题.您对此有何看法? (171认同)
  • @donohoe其实你在2010年8月回答了:) (32认同)
  • 还有一个问题,如何将此标签中的图像保存到服务器.任何猜测? (14认同)
  • 它会使用更少的内存来执行类似`var img = new Image(); img.src = canvas.toDataURL(); document.body.appendChild(IMG);`.该`document.write`代码使数据URL,他们制作的HTML字符串,然后把这个字符串的副本在DOM,浏览器则必须解析HTML字符串,把另一份的图像元素,然后解析它再次将数据URL转换为图像数据,最后它可以显示图像.对于屏幕大小的图像,这是一个巨大的内存/复制/解析.只是一个建议 (11认同)
  • 但是如果我使用var img = canvas.toDataURL("image/jpeg"); 我的背景是完整的黑色.如何纠正这一点 (6认同)
  • 惊人!我已将它与Processing.js一起使用 (3认同)
  • @Gauti你的背景可能是RGBA颜色(0,0,0,0),即完全透明的黑色.JPEG不支持透明度,因此我认为这只是转换为黑色. (3认同)
  • @Surya - 在上面的例子中,我将使用AJAX将img变量POST到服务器.或者,您可以在表单中设置隐藏字段的值. (2认同)
  • 对我不起作用 - 对于“png”,我得到透明框图像(没有可见数据),对于“jpeg”,与上面报告的相同 - 全黑。有任何想法吗? (2认同)

oll*_*iej 113

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>
Run Code Online (Sandbox Code Playgroud)

从理论上讲,这应该创建然后导航到中间有绿色方块的图像,但我还没有测试过.

  • 图像将在浏览器中显示为图像.然后,您可以将其保存到磁盘或其他任何.这是一个快速而又脏的通用"Canvas2PNG"书签,它将页面中的第一个画布转换为PNG,并在新窗口中将其显示在浏览器中:`javascript:void(window.open().location = document.getElementsByTagName("canvas) ")[0] .toDataURL(" 图像/ PNG"))` (5认同)
  • 图像将被保存的位置.在我当地的位置? (2认同)

mei*_*ome 42

我想我会扩展这个问题的范围,在这个问题上有一些有用的花絮.

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

var canvas = document.getElementById("mycanvas");
var image = canvas.toDataURL("image/png");
Run Code Online (Sandbox Code Playgroud)

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

document.write('<img src="'+image+'"/>');
Run Code Online (Sandbox Code Playgroud)

其中"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];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

如果您希望让用户在保存文件时下载该文件,您可以执行以下操作:

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;
Run Code Online (Sandbox Code Playgroud)

如果您使用不同的mime类型,请务必更改image/png的两个实例,而不是image/octet-stream.还值得一提的是,如果在渲染画布时使用任何跨域资源,则在尝试使用toDataUrl方法时将遇到安全性错误.

  • 在<a> link和.click()上使用target ="_ blank"它也应该可以触发下载(使用FF data-urls和download ="filename"测试text/csv和text/plain) (2认同)

dav*_*zen 32

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);
}
Run Code Online (Sandbox Code Playgroud)


lep*_*epe 21

我会用" wkhtmltopdf ".它工作得很好.它使用webkit引擎(用于Chrome,Safari等),它非常易于使用:

wkhtmltopdf stackoverflow.com/questions/923885/ this_question.pdf
Run Code Online (Sandbox Code Playgroud)

而已!

试试吧


小智 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");
Run Code Online (Sandbox Code Playgroud)

- 创建图像

$data = $_POST['data'];
$img = imagecreatefromstring(base64_decode(substr($data,strpos($data,',')+1)));
Run Code Online (Sandbox Code Playgroud)

- 出口图像为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();
Run Code Online (Sandbox Code Playgroud)

- 或透明的PNG

imagesavealpha($img, true);
imagepng($img);
die($img);
Run Code Online (Sandbox Code Playgroud)


Cyb*_*axs 9

另一个有趣的解决方案是PhantomJS.这是一个使用JavaScript或CoffeeScript的无头WebKit脚本.

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

最佳入口点是屏幕截图维基页面.

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

>phantomjs rasterize.js http://raphaeljs.com/polar-clock.html clock.png
Run Code Online (Sandbox Code Playgroud)

您要将页面呈现为PDF吗?

> phantomjs rasterize.js 'http://en.wikipedia.org/w/index.php?title=Jakarta&printable=yes' jakarta.pdf
Run Code Online (Sandbox Code Playgroud)

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

can*_*ero 8

这是另一种方式,没有字符串,尽管我真的不知道它是否更快。而不是 toDataURL (正如这里提出的所有问题)。在我的情况下,我想阻止 dataUrl/base64,因为我需要一个数组缓冲区或视图。所以 HTMLCanvasElement 中的另一个方法是toBlob. (打字稿功能):

    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));
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 该答案必须标记为正确答案并需要投票。谢谢! (2认同)