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

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


HTML5提供Canvas.toDataURL(mimetype),它在Opera、Firefox和Safari4测试版中实现。然而,有许多安全限制(主要是与将内容从另一个来源绘制到画布上有关)。

因此,您不需要额外的库。

e.g.

 <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>

理论上,这应该创建一个中间有绿色方块的图像,然后导航到该图像,但我还没有进行测试。


最初的答案是针对一个类似的问题。已修订如下:

const canvas = document.getElementById('mycanvas')
const img    = canvas.toDataURL('image/png')

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

document.getElementById('existing-image-id').src = img

or

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

我会使用“wkhtmltopdf”。它工作得很好。它使用webkit引擎(在Chrome、Safari等中使用),并且非常容易使用:

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

就是这样!

试试看


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

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

最好的切入点是屏幕捕获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

我想我会把这个问题的范围扩大一点,在这个问题上提供一些有用的花絮。

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

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流。还值得一提的是,如果在渲染画布时使用任何跨域资源,则在尝试使用toDataUrl方法时会遇到安全错误。


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

-使用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);

如果您正在使用jQuery(很多人都这么做),那么您可以这样实现接受的答案:

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

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

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);
}

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

使用绘制图像函数ctx.drawImage(image1,0,0,w,h);在画布上单击鼠标右键


您可以使用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


这是另一种方式,没有字符串,尽管我不知道它是否更快。而不是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));
}

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

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


简单的答案就是获取它的blob并将imgsrc设置为该blob的新对象URL,然后使用一些库将该图像添加到PDF中,例如

var ok=document.createElement(“画布”)正常宽度=400ok.height=140var ctx=ok.getContext(“2d”);for(设k=0;k<ok.height;k++)(k% 数学楼层((数学.随机()) *10)== 0)&&(y=>){对于(var i=0;i<ok.width;i++){如果(i%25==0){ctx.globalAlpha=数学随机()ctx.fillStyle=(“rgb(”+数学random()*255+“,”+数学random()*255+“,”+数学random()*255+“)”);(wdth=>ctx.fill矩形(数学.sin(i*数学.PI/180) * 数学.随机()*ok宽度,数学科(i*数学PI/180,)*wdth+y,wdth中,世界贸易组织))(15)}}})(k)ok。toBlob(blob=>{k.src=URL.createObjectURL(blob)})<img id=k>

或者,如果您想使用低级字节数据,可以获取画布的原始字节,然后根据文件规范将原始图像数据写入数据的必要字节。您只需要调用ctx.getImageData(0,0,ctx.canvas.widht,ctx.画布.height)来获取原始图像数据,然后根据文件规范将其写入


如果你想让画布消失,你可以使用这个片段

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id=canvas width=200 height=200></canvas>
    <iframe id='img' width=200 height=200></iframe>
    <script>
        window.onload = function() {
            var canvas = document.getElementById("canvas");
            var context = canvas.getContext("2d");
            context.fillStyle = "green";
            context.fillRect(50, 50, 100, 100);
            document.getElementById('img').src = canvas.toDataURL("image/jpeg");
            console.log(canvas.toDataURL("image/jpeg"));
        }
    </script>
</body>
</html>

从<canvas/>上载图像:

async function canvasToBlob(canvas) {
  if (canvas.toBlob) {
    return new Promise(function (resolve) {
      canvas.toBlob(resolve)
    })
  } else {
    throw new Error('canvas.toBlob Invalid')
  }
}

await canvasToBlob(yourCanvasEl)