Зробіть 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.