Захватить холст HTML как gif/jpg/png/pdf?

Можно ли захватить или распечатать то, что отображается в HTML-холсте в виде изображения или PDF?

Я хотел бы сгенерировать изображение через холст и быть в состоянии сгенерировать png из этого изображения.

16 ответов

Решение

К сожалению. Оригинальный ответ был конкретным для аналогичного вопроса. Это было пересмотрено:

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

со значением в IMG вы можете записать его в виде нового изображения следующим образом:

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

HTML5 предоставляет Canvas.toDataURL(mimetype), который реализован в бета-версиях Opera, Firefox и Safari 4. Однако существует ряд ограничений безопасности (в основном для рисования контента из другого источника на холсте).

Так что вам не нужна дополнительная библиотека.

например

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

Теоретически это должно создать и затем перейти к изображению с зеленым квадратом в середине, но я не проверял.

Я думал, что немного расширю сферу этого вопроса, с некоторыми полезными подробностями по этому вопросу.

Чтобы получить холст как изображение, вам необходимо сделать следующее:

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.

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

Я бы использовал " http://wkhtmltopdf.org/". Это просто отлично работает. Он использует движок webkit (используется в Chrome, Safari и т. Д.), И его очень легко использовать:

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

Это оно!

Попытайся

Вот некоторая помощь, если вы делаете загрузку через сервер (таким образом вы можете назвать / конвертировать / постобработать / и т. Д. Ваш файл):

-Попубликовать данные с помощью 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);

Это другой способ, без строк, хотя я действительно не знаю, быстрее он или нет. Вместо 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));
}

Еще одно преимущество больших двоичных объектов заключается в том, что вы можете создавать ObjectUrls для представления данных в виде файлов, подобно члену HTMLInputFile'files '. Больше информации:

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

Другое интересное решение - PhantomJS. Это безголовый сценарий WebKit с JavaScript или CoffeeScript.

Одним из вариантов использования является захват экрана: вы можете программно захватывать веб-контент, включая SVG и Canvas, и / или создавать скриншоты веб-сайта с предварительным просмотром миниатюр.

Лучшей точкой входа является вики-страница захвата экрана.

Вот хороший пример для полярных часов (от 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

Если вы используете jQuery, что делают многие, то вы бы реализовали принятый ответ следующим образом:

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

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

The key point is

canvas.toDataURL(type, quality)


And I want to provide an example for someone like me who wants to save SVG to PNG(also can add some text if you wish), which may be from an Online source or font-awesome icon, etc.

Example

100% javascript and no other 3-rd library.

if you want to run on stackoverflow and move your mouse on the picture may get error

DOMException: The Clipboard API has been blocked because of a permissions policy applied to the current document

You can copy the code on your local machine and run it again, will be fine.

Вы можете использовать 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

upload image from <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)

В некоторых версиях Chrome вы можете:

  1. Используйте функцию рисования изображения ctx.drawImage(image1, 0, 0, w, h);
  2. Щелкните правой кнопкой мыши на холсте

Простой ответ - просто взять его и установить img src на новый URL-адрес объекта этого большого двоичного объекта, а затем добавить это изображение в PDF, используя некоторую библиотеку, например

var ok = document.createElement("canvas")
ok.width = 400
ok.height = 140
var ctx = ok.getContext("2d");
for(let k = 0; k < ok.height; k++) 
  (
    k 
    % 
    Math.floor(
      (
        Math.random()
      ) *
      10
    )
    == 
    0
  ) && (y => {
    for(var i = 0; i < ok.width; i++) {
      if(i % 25 == 0) {
        ctx.globalAlpha = Math.random()
        ctx.fillStyle = (
          "rgb(" + 
          Math.random() * 255 + "," +
          Math.random() * 255 + "," +
          Math.random() * 255 + ")"
        );

        (wdth =>
          ctx.fillRect(
            Math.sin(
              i * Math.PI / 180
            ) * 
              Math.random() *
              ok.width,
            Math.cos(
              i * Math.PI / 180,
            ) * wdth + y,
            wdth,
            wdth
          )
        )(15)
      }
    }
  })(k)

ok.toBlob(blob => {
  k.src = URL.createObjectURL(blob)
})
<img id=k>

В качестве альтернативы, если вы хотите работать с низкоуровневыми байтовыми данными, вы можете получить необработанные байты холста, а затем, в зависимости от спецификации файла, записать необработанные данные изображения в необходимые байты данных. тебе просто нужно позвонитьctx.getImageData(0, 0, ctx.canvas.widht, ctx.canvas.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>

Capture to a Gif (в распакованном виде ) — это расширение Chrome для записи HTML-холста в файл GIF.

постобработка: вам нужно будет вырезать и сжать видео (ffmpeg, kdenlive,...)

зачем сжимать? результат будет иметь постоянную частоту кадров, а не исходную частоту кадров. это ограничение всех инструментов записи холста ( ccapture , jsgif, gif-capture-canvas, ...)

Другие вопросы по тегам