Зробіть HTML-полотно як gif / jpg / png / pdf?


719

Чи можливо захопити чи роздрукувати те, що відображається на HTML-полотні у вигляді зображення чи PDF?

Я хотів би генерувати зображення за допомогою полотна та мати змогу генерувати PNG з цього зображення.


Ось віще рішення: stackoverflow.com/questions/19395649 / ... в доповненні до відповіді stackoverflow.com/a/3514404/529442
— Євген Gr. Філіппов


Приклад тут freakyjolly.com/…
— Code Spy

1
Можливо, ви знайдете корисну для цього бібліотеку canvas2image: github.com/hongru/canvas2image
— noego

Відповіді:


737

На жаль Оригінальна відповідь була специфічною для аналогічного питання. Це було переглянуто:

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

зі значенням у IMG ви можете записати його як нове зображення так:

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

15
ще одне питання, як я можу зберегти зображення, яке я отримав у цьому тезі, на сервері. Будь-яка здогадка ??
— Суря

7
Але якщо я використовую var img = canvas.toDataURL ("image / jpeg"); я отримую фон як повний чорний. Як виправити це
— gauti

181
О, давай. Я відповів на це у 2009 році. Що ви очікуєте?
— донохое

35
@donohoe насправді ти відповів на це в серпні 2010 р. :)
— нік

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 (міметик), який реалізований в 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"))
— Кай Карвер

Якщо зображення має розмір декількох Мб, підготуйтеся до збою вашого браузера (я це робив ще раз у FireFox).
— jahu

1
Як це можна змінити, щоб відобразити кілька зображень?
— Менталіст

URI даних мають максимальну довжину, тому розмір зображення є верхньою межею, яку ви можете встановити до URL-адреси даних.
— Juha Syrjälä

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, щойно завантажений?
— So4ne

1
@ So4ne Я не думаю, що це повинно бути зображення / octet-stream, щоб спонукати користувача до завантаження. Якщо ви позбудетесь цього рядка, ви перейдете на сторінку, що переспрямовується на зображення. Я хотів би знати, якщо хтось інший знає спосіб зробити це красиво, хоча.
— meiamsome

2
використовуючи мішень = «_blank» на <a> посиланням і .click () вона повинна працювати, теж , щоб викликати завантаження (протестовано з FF дата-адреси і завантаження = «ім'я файлу» для тексту / CSV і текст / звичайний)
— Ax3l

Це чудово. Дякую! Але що робити, якщо я хочу зберегти на сервері, а не локальному? Чи прийме вхідний файл форми форми img src як щось, що можна завантажити?
— головний алхімік

На жаль Щойно знайшов відповідь. Залишаючи попереднє запитання на випадок, якщо хтось ще виглядає так, як 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

Це приємне рішення, за винятком того, що воно може не працювати на IE. Помилка отримання "Площа даних, передана системному дзвінку, занадто мала"
— Хосе Черіан

У Chrome він говорить "Мережна помилка", тоді як у Firefox це чудово працює. (На Linux)
— Ecker00

20

Я б використовував " wkhtmltopdf ". Це просто чудово працює. Він використовує двигун webkit (використовується в Chrome, Safari тощо), і це дуже просто:

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

Це воно!

Спробуй це


1
Я теж у таборі wkhtmltopdf. Ми використовуємо його для архівування та його ДУМОВОГО.
— Даніель Сабо

Як використовувати WKHTMLtoPDF на сторінці, для якої потрібна інформація про вхід? Я використовую Jsreport для перетворення в PDF, але я захоплюю свій вміст за допомогою HTML2Canvas, у мене проблема з надсиланням полотна як параметр на JSreport
— khaled Dehia

@khaledDehia перевірити: stackoverflow.com/questions/10287386 / ...
— Lepe

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.

Одним із випадків використання є захоплення екрана: ви можете програмно захоплювати веб-вміст, включаючи 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

2
+1: PhantomJS - це проста, добре задокументована та продумана система, яка ідеально підходить для цієї роботи. Це дозволяє набагато більше, ніж просто захопити полотно - наприклад, ви можете змінити сторінку або її частину (через JS) перед захопленням, щоб зробити так, щоб вона виглядала так, як ви хочете. Ідеально!
— johndodo

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

У мене є проблема збереження, якась допоможе мені переглянути це посилання: stackoverflow.com/questions/25131763/…
— Ramesh S

2
Чисте (100%) рішення jQuery таке: $('<img>').attr('src',$('#mycanvas')[0].toDataURL('image/png')).appendTo($('#element-to-write-to').empty());Рівно один рядок.
— Наель Макссудов

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

Ще однією перевагою крапів є те, що ви можете створити ObjectUrls для представлення даних у вигляді файлів, подібних до учасників HTMLInputFile. Більше інформації:

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


-1

У деяких версіях Chrome ви можете:

  1. Використовуйте функцію малювання зображення ctx.drawImage(image1, 0, 0, w, h);
  2. Клацніть правою кнопкою миші на полотні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.