Cattura la tela HTML come gif / jpg / png / pdf?


719

È possibile catturare o stampare ciò che viene visualizzato in una tela html come immagine o pdf?

Vorrei generare un'immagine tramite tela ed essere in grado di generare un png da quell'immagine.





1
Potresti trovare utile la libreria canvas2image per questo: github.com/hongru/canvas2image
noego

Risposte:


737

Ops. La risposta originale era specifica per una domanda simile. Questo è stato rivisto:

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

con il valore in IMG puoi scriverlo come una nuova immagine in questo modo:

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

15
ancora una domanda, come posso salvare l'immagine che ho ottenuto con questo tag sul server? Qualche ipotesi ??
Surya,

7
Ma se uso var img = canvas.toDataURL ("image / jpeg"); sto ottenendo lo sfondo come nero completo. Come rettificarlo
gauti il

181
Oh andiamo. Ho risposto a questo nel 2009. Cosa ti aspetti?
Donohoe,

35
@donohoe in realtà hai risposto ad agosto 2010 :)
nick

13
Userebbe molta meno memoria per fare qualcosa del genere var img = new Image(); img.src = canvas.toDataURL(); document.body.appendChild(img);. Il document.writecodice crea l'URL dei dati, creano una stringa HTML, quindi inserisce una copia di quella stringa nel DOM, il browser deve quindi analizzare quella stringa HTML, inserirne un'altra copia sull'elemento immagine, quindi analizzarla nuovamente per attivare dati URL in dati immagine, quindi finalmente può mostrare l'immagine. Per un'immagine di dimensioni dello schermo che è un'enorme quantità di memoria / copia / analisi. Solo un suggerimento
Gman

116

HTML5 fornisce Canvas.toDataURL (mimetype) implementato in Opera, Firefox e Safari 4 beta. Esistono tuttavia alcune restrizioni di sicurezza (principalmente legate al disegno di contenuti di un'altra origine sulla tela).

Quindi non hai bisogno di una libreria aggiuntiva.

per esempio

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

Teoricamente questo dovrebbe creare e quindi navigare verso un'immagine con un quadrato verde nel mezzo di esso, ma non ho ancora testato.


2
Dove verrà salvata l'immagine. Posizione nel mio locale?
chinna_82,

5
l'immagine verrà visualizzata come immagine nel tuo browser. È quindi possibile salvarlo su disco o altro. Ecco un bookmarklet generico "Canvas2PNG" veloce e sporco che converte la prima tela della pagina in PNG e la visualizza nel browser in una nuova finestra:javascript:void(window.open().location = document.getElementsByTagName("canvas")[0].toDataURL("image/png"))
Kai Carver

Se l'immagine ha una dimensione di pochi MB, preparati a bloccare il browser (l'ho fatto qualche tempo fa in FireFox).
jahu

1
Come potrebbe essere modificato per renderizzare più immagini?
Mentalista,

Gli URI dei dati hanno una lunghezza massima, quindi esiste un limite massimo per le dimensioni di un'immagine che è possibile inserire in un url di dati.
Juha Syrjälä,

44

Ho pensato di estendere un po 'la portata di questa domanda, con alcune utili notizie in merito.

Per ottenere la tela come immagine, è necessario effettuare le seguenti operazioni:

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

Puoi usarlo per scrivere l'immagine nella pagina:

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

Dove "image / png" è un tipo mime (png è l'unico che deve essere supportato). Se desideri una matrice dei tipi supportati, puoi fare qualcosa del genere:

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

Devi eseguirlo solo una volta per pagina, non dovrebbe mai cambiare durante il ciclo di vita di una pagina.

Se desideri che l'utente scarichi il file mentre viene salvato, puoi effettuare le seguenti operazioni:

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;

Se lo stai usando con diversi tipi di mime, assicurati di cambiare entrambe le istanze di image / png, ma non l'immagine / flusso di ottetti. Vale anche la pena ricordare che se si utilizzano risorse tra domini per il rendering del canvas, si verificherà un errore di sicurezza quando si tenta di utilizzare il metodo toDataUrl.


1
Con la tua soluzione per il download del file, devo scegliere il software che voglio usare, è un po 'scomodo ... C'è un modo per sostituire nuovamente il mime come png una volta scaricato?
So4ne,

1
@ So4ne Non credo, deve essere un'immagine / flusso di ottetti per richiedere all'utente un download. Se ti sbarazzi di quella linea, finirai con la pagina che reindirizza all'immagine. Mi piacerebbe sapere se qualcun altro conosce un modo per farlo bene, però.
Meiamsome il

2
usando target = "_ blank" su <a> link e .click () dovrebbe funzionare anche per attivare il download (testato con dati-url FF e download = "nomefile" per text / csv e text / plain)
Ax3l

Questo è fantastico Grazie! E se volessi salvare sul server e non sul locale? Un input di file di modulo accetterà img src come qualcosa che può essere caricato?
Chief Alchemist,

Ops. Ho appena trovato la risposta. Lasciare la domanda precedente nel caso in cui qualcun altro stia cercando anche 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);
}

Il file salvato rimane nel formato .svg. Come salvarlo come png?
nullpointer

Questa è una buona soluzione, tranne per il fatto che potrebbe non funzionare su IE. Errore "L'area dati trasmessa a una chiamata di sistema è troppo piccola"
Jose Cherian,

In Chrome dice "Errore di rete", mentre in Firefox funziona alla grande. (Su Linux)
Ecker00

20

Vorrei usare " wkhtmltopdf ". Funziona alla grande. Utilizza il motore webkit (utilizzato in Chrome, Safari, ecc.) Ed è molto facile da usare:

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

Questo è tutto!

Provalo


1
Sono anche nel campo wkhtmltopdf. Lo abbiamo usato per l'archiviazione e la sua INCREDIBILITÀ.
Daniel Szabo,

Come usare WKHTMLtoPDF nella pagina che ha richiesto le informazioni di accesso? Sto usando Jsreport per convertire in PDF ma acquisisco il mio contenuto con HTML2Canvas, ho problemi con l'invio di Canvas come parametro a JSreport
khaled Dehia,


15

Ecco qualche aiuto se esegui il download attraverso un server (in questo modo puoi nominare / convertire / post-process / etc il tuo file):

-Post dati utilizzando toDataURL

-Impostare le intestazioni

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

-creare l'immagine

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

-esporta l'immagine come 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();

-o come PNG trasparente

imagesavealpha($img, true);
imagepng($img);
die($img);

9

Un'altra soluzione interessante è PhantomJS . È un WebKit senza testa programmabile con JavaScript o CoffeeScript.

Uno dei casi d'uso è l'acquisizione di schermate: è possibile acquisire a livello di codice contenuti Web, inclusi SVG e Canvas e / o creare schermate di siti Web con anteprima in anteprima.

Il miglior punto di ingresso è la pagina wiki di cattura schermo .

Ecco un buon esempio di orologio polare (da RaphaelJS):

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

Vuoi rendere una pagina in un PDF?

> phantomjs rasterize.js 'http://en.wikipedia.org/w/index.php?title=Jakarta&printable=yes' jakarta.pdf

2
+1: PhantomJS è un sistema semplice, ben documentato e ben pensato, perfetto per questo lavoro. Permette molto di più che afferrare anche una tela: ad esempio, è possibile modificare la pagina o parte di essa (tramite JS) prima di afferrarla, quindi farla apparire nel modo desiderato. Perfetto!
johndodo,

1
PhantomJs è ormai obsoleto
Merc

3

Se stai usando jQuery, cosa che fanno molte persone, allora implementeresti la risposta accettata in questo modo:

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

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

12
Nota che l' unico uso di jQuery qui è la selezione della tela. .toDataURLè JS nativo.
j6m8,

Ho un problema di salvataggio che qualcuno può aiutarmi a vedere questo link: stackoverflow.com/questions/25131763/…
Ramesh S

2
La soluzione jQuery pura (100%) è la seguente: $('<img>').attr('src',$('#mycanvas')[0].toDataURL('image/png')).appendTo($('#element-to-write-to').empty());esattamente una riga.
Naeel Maqsudov,

1

Puoi usare jspdf per catturare una tela in un'immagine o pdf in questo modo:

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

Ulteriori informazioni: https://github.com/MrRio/jsPDF


1

Questo è l'altro modo, senza stringhe, anche se non so se sia più veloce o meno. Invece di toDataURL (come tutte le domande qui proposte). Nel mio caso voglio impedire dataUrl / base64 poiché ho bisogno di un buffer o di una vista di array. Quindi l'altro metodo in HTMLCanvasElement è toBlob. (Funzione 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));
}

Un altro vantaggio dei BLOB è che è possibile creare ObjectUrl per rappresentare i dati come file, in modo simile al membro 'file' di HTMLInputFile. Ulteriori informazioni:

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


-1

Su alcune versioni di Chrome, puoi:

  1. Utilizzare la funzione Disegna immagine ctx.drawImage(image1, 0, 0, w, h);
  2. Fare clic con il tasto destro sulla tela
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.