Abadikan Kanvas HTML sebagai gif / jpg / png / pdf?

719

Apakah mungkin untuk mengambil atau mencetak apa yang ditampilkan di kanvas html sebagai gambar atau pdf?

Saya ingin menghasilkan gambar melalui kanvas, dan dapat menghasilkan png dari gambar itu.

Parand
sumber
Inilah solusi pythonic: stackoverflow.com/questions/19395649/... selain menjawab stackoverflow.com/a/3514404/529442
Eugene Gr. Philippov
Contoh di sini freakyjolly.com/...
Code Spy
1
Anda mungkin menemukan perpustakaan canvas2image berguna untuk ini: github.com/hongru/canvas2image
noego

Jawaban:

737

Ups. Jawaban asli khusus untuk pertanyaan serupa. Ini telah direvisi:

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

dengan nilai dalam IMG Anda dapat menuliskannya sebagai Gambar baru seperti:

document.write('<img src="'+img+'"/>');
donohoe
sumber
15
satu pertanyaan lagi, bagaimana saya bisa menyimpan gambar yang saya dapatkan di tag ini ke server. Tebak ??
Surya
7
Tetapi jika saya menggunakan var img = canvas.toDataURL ("image / jpeg"); Saya mendapatkan latar belakang sebagai hitam lengkap. Bagaimana cara memperbaikinya
gauti
181
Oh ayolah. Saya menjawab ini pada tahun 2009. Apa yang Anda harapkan?
donohoe
35
@donohoe sebenarnya Anda menjawabnya pada Agustus 2010 :)
nick
13
Itu akan menggunakan memori jauh lebih sedikit untuk melakukan sesuatu seperti var img = new Image(); img.src = canvas.toDataURL(); document.body.appendChild(img);. The document.writekode membuat URL data, mereka membuat string HTML, kemudian menempatkan salinan string yang di DOM, browser kemudian harus mengurai bahwa string HTML, menempatkan salinan lain pada elemen gambar, kemudian mengurai lagi untuk menghidupkan URL data menjadi data gambar, lalu akhirnya bisa menampilkan gambar. Untuk gambar ukuran layar, itu adalah memori / penyalinan / parsing yang sangat besar. Hanya sebuah saran
gman
116

HTML5 menyediakan Canvas.toDataURL (mimetype) yang diimplementasikan di Opera, Firefox, dan Safari 4 beta. Namun ada beberapa batasan keamanan (sebagian besar berkaitan dengan menggambar konten dari asal lain ke kanvas).

Jadi Anda tidak perlu perpustakaan tambahan.

misalnya

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

Secara teoritis ini harus membuat dan kemudian menavigasi ke gambar dengan kotak hijau di tengahnya, tapi saya belum menguji.

olliej
sumber
2
Di mana gambar akan disimpan. Lokasi di lokal saya?
chinna_82
5
gambar akan ditampilkan sebagai gambar di browser Anda. Anda kemudian dapat menyimpannya ke disk atau apa pun. Berikut adalah bookmarklet generik yang cepat dan kotor "Canvas2PNG" yang mengubah kanvas pertama di halaman menjadi PNG dan menampilkannya di browser di jendela baru:javascript:void(window.open().location = document.getElementsByTagName("canvas")[0].toDataURL("image/png"))
Kai Carver
Jika ukuran gambarnya beberapa MB, bersiaplah untuk menghancurkan browser Anda (saya pernah melakukannya di FireFox).
jahu
1
Bagaimana ini bisa dimodifikasi untuk membuat beberapa gambar?
Mentalist
URI data memiliki panjang maksimal, sehingga ada batas atas pada ukuran gambar yang dapat Anda tempatkan ke url data.
Juha Syrjälä
44

Saya pikir saya akan sedikit memperluas cakupan pertanyaan ini, dengan beberapa informasi berguna tentang masalah ini.

Untuk mendapatkan kanvas sebagai gambar, Anda harus melakukan hal berikut:

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

Anda dapat menggunakan ini untuk menulis gambar ke halaman:

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

Di mana "image / png" adalah tipe mime (png adalah satu-satunya yang harus didukung). Jika Anda ingin array tipe yang didukung, Anda dapat melakukan sesuatu di sepanjang baris ini:

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

Anda hanya perlu menjalankan ini sekali per halaman - itu tidak akan pernah berubah melalui siklus hidup halaman.

Jika Anda ingin membuat pengguna mengunduh file saat disimpan, Anda dapat melakukan hal berikut:

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;

Jika Anda menggunakannya dengan tipe mime yang berbeda, pastikan untuk mengubah kedua instance gambar / png, tetapi tidak untuk image / octet-stream. Perlu juga disebutkan bahwa jika Anda menggunakan sumber daya lintas-domain dalam merender kanvas Anda, Anda akan menemukan kesalahan keamanan ketika Anda mencoba menggunakan metode toDataUrl.

meiamsome
sumber
1
Dengan solusi Anda untuk mengunduh file, saya harus memilih perangkat lunak yang ingin saya gunakan, ini agak tidak nyaman ... Apakah ada cara untuk mengganti kembali mime sebagai png setelah diunduh?
So4ne
1
@ So4ne Saya tidak berpikir begitu, itu harus berupa image / octet-stream untuk meminta pengguna mengunduh. Jika Anda menghilangkan garis itu, Anda akan berakhir dengan halaman yang diarahkan ke gambar. Saya ingin tahu apakah ada orang lain yang tahu cara melakukan ini dengan baik.
meiamsome
2
menggunakan target = "_ blank" pada tautan <a> dan .click () itu akan berfungsi juga untuk memicu unduhan (diuji dengan FF data-url dan unduh = "nama file" untuk teks / csv dan teks / polos)
Ax3l
Ini bagus. Terima kasih! Tetapi bagaimana jika saya ingin menyimpan ke server dan bukan lokal? Apakah input file formulir menerima img src sebagai sesuatu yang dapat diunggah?
Ketua Alchemist
Ups. Baru menemukan jawabannya. Meninggalkan pertanyaan sebelumnya kalau-kalau ada orang lain juga melihat stackoverflow.com/questions/13198131/…
Chief Alchemist
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);
}
david.barkhuizen
sumber
File yang disimpan tetap dalam format .svg. Bagaimana cara menyimpannya sebagai png?
nullpointer
Ini adalah solusi yang bagus kecuali itu mungkin tidak berfungsi pada IE. Mendapatkan kesalahan "Area data yang diteruskan ke panggilan sistem terlalu kecil"
Jose Cherian
Di Chrome dikatakan "Kesalahan jaringan", sementara di Firefox berfungsi dengan baik. (Di Linux)
Ecker00
20

Saya akan menggunakan " wkhtmltopdf ". Itu hanya bekerja dengan baik. Ini menggunakan mesin webkit (digunakan di Chrome, Safari, dll.), Dan sangat mudah digunakan:

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

Itu dia!

Cobalah

lepe
sumber
1
Saya di kamp wkhtmltopdf juga. Kami telah menggunakannya untuk pengarsipan dan AMAZING.
Daniel Szabo
Bagaimana cara menggunakan WKHTMLtoPDF di halaman yang memerlukan info masuk? Saya menggunakan Jsreport untuk mengonversi ke PDF tapi saya menangkap konten saya dengan HTML2Canvas, saya memiliki masalah dengan mengirimkan Kanvas sebagai parameter ke JSreport
khaled Dehia
15

Berikut ini beberapa bantuan jika Anda melakukan pengunduhan melalui server (dengan cara ini Anda dapat memberi nama / konversi / pasca-proses / dll file Anda):

-Post data menggunakan toDataURL

-Mengatur header

$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");

-membuat gambar

$data = $_POST['data'];
$img = imagecreatefromstring(base64_decode(substr($data,strpos($data,',')+1)));

Gambar -ekspor sebagai 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();

-atau PNG transparan

imagesavealpha($img, true);
imagepng($img);
die($img);
Komunitas
sumber
9

Solusi menarik lainnya adalah PhantomJS . Ini adalah skrip WebKit tanpa kepala dengan JavaScript atau CoffeeScript.

Salah satu kasus penggunaannya adalah tangkapan layar: Anda dapat secara terprogram menangkap konten web, termasuk SVG dan Kanvas dan / atau Buat tangkapan layar situs web dengan pratinjau thumbnail.

Titik masuk terbaik adalah halaman wiki tangkapan layar .

Ini adalah contoh yang bagus untuk jam polar (dari RaphaelJS):

>phantomjs rasterize.js http://raphaeljs.com/polar-clock.html clock.png

Apakah Anda ingin merender halaman ke PDF?

> phantomjs rasterize.js 'http://en.wikipedia.org/w/index.php?title=Jakarta&printable=yes' jakarta.pdf
Cybermaxs
sumber
2
+1: PhantomJS adalah sistem yang sederhana, terdokumentasi dengan baik dan dipikirkan dengan matang, sempurna untuk pekerjaan ini. Ini memungkinkan lebih dari sekedar mengambil kanvas juga - misalnya, Anda dapat memodifikasi halaman atau bagian dari itu (melalui JS) sebelum mengambilnya sehingga membuatnya terlihat seperti yang Anda inginkan. Sempurna!
johndodo
1
PhantomJs sekarang sudah usang
Merc
3

Jika Anda menggunakan jQuery, yang dilakukan banyak orang, maka Anda akan menerapkan jawaban yang diterima seperti:

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

$("#elememt-to-write-to").html('<img src="'+img+'"/>');
Ternak
sumber
12
Perhatikan bahwa satu - satunya penggunaan jQuery di sini adalah pemilihan kanvas. .toDataURLadalah asli JS.
j6m8
Saya telah menyimpan masalah, seseorang dapat membantu saya melihat tautan ini: stackoverflow.com/questions/25131763/…
Ramesh S
2
Solusi jQuery murni (100%) adalah sebagai berikut: $('<img>').attr('src',$('#mycanvas')[0].toDataURL('image/png')).appendTo($('#element-to-write-to').empty());Persis satu baris.
Naeel Maqsudov
1

Anda dapat menggunakan jspdf untuk menangkap kanvas ke dalam gambar atau pdf seperti ini:

var imgData = canvas.toDataURL('image/png');              
var doc = new jsPDF('p', 'mm');
doc.addImage(imgData, 'PNG', 10, 10);
doc.save('sample-file.pdf');

Info lebih lanjut: https://github.com/MrRio/jsPDF

ferralucho
sumber
1

Ini adalah cara lain, tanpa ikatan meskipun saya tidak benar-benar tahu apakah lebih cepat atau tidak. Alih-alih toDataURL (karena semua pertanyaan di sini mengusulkan). Dalam kasus saya ingin mencegah dataUrl / base64 karena saya memerlukan buffer atau view Array. Jadi metode lain dalam HTMLCanvasElement adalah toBlob. (Fungsi 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));
}

Keuntungan lain dari blob adalah Anda dapat membuat ObjectUrls untuk merepresentasikan data sebagai file, mirip dengan anggota 'file' HTMLInputFile. Info lebih lanjut:

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

kankerbero
sumber
-1

Pada beberapa versi Chrome, Anda dapat:

  1. Gunakan fungsi menggambar gambar ctx.drawImage(image1, 0, 0, w, h);
  2. Klik kanan pada kanvas
Peter
sumber