Library einbinden
Die Library wird von github.com/parallax/jsPDF geladen. Nur eine Datei in dem Paket jsPDF-master ist wichtig: jsPDF-master/dist/jsPDF.min.js (~ 300 KB). Wie meist: Am besten in den Seitenfuß, vor dem schließenden body-Tag.
<script type="text/javascript" src="jspdf.min.js"></script>
PDF-Objekt erzeugen
Den Anfang machen das Erzeugen des PDF-Objekts und das Festlegen des Formats (p = Porträt, mm = Maßeinheit, a4 = Seitengröße)
var pdf = new jsPDF("p", "mm", "a4");
oder
var pdf = new jsPDF ( { orientation: "landscape", unit: "mm", format: [297,210] });
Ausgaben erzeugen
Ab jetzt ist Rechnen gefragt, denn jede Ausgabe muss platziert werden. Den Text Hallo Welt auf Postion 20mm von links, 30 mm von rechts ausgeben:
pdf.text ("ESTESTAS SEMPER LOREM", 20, 30);
Eine zweite Seite anhängen mit addPage
pdf.addPage(); pdf.text ("Hallo Universum!", 20, 30);
Das PDF muss nur noch gespeichert werden, allerdings am besten mit einem Link oder Button, denn sonst wird das PDF direkt beim Aufruf der Seite geladen.
<button id="laden">PDF laden</button> document.querySelector("#laden").onclick = function () { pdf.save ("hallowelt.pdf"); }
Text, Linien, Rechtecke und Kreise
jsPDF gibt Text, Bilder, Rechtecke, Kreise und Linien aus und lehnt sich eng an Javascript Canvas an.
pdf.setTextColor(110,120,82); // Textfarbe als RGB-Werte pdf.setFontSize(42); // Schriftgröße pdf.setFont("times") pdf.setFontType("bold") pdf.text ("EGESTAS SEMPER LOREM", 50, 20); // Text platzieren pdf.setDrawColor(110,120,82); // Farbe für Linien als RGB-Werte pdf.setLineWidth(1); // Breite der Linie in mm pdf.line(25, 26, 270, 26); // Linie von 25 bis 270 mm
Rechteck zeichnen
pdf.setLineWidth(0.5); pdf.setDrawColor(220,220,220); pdf.rect (25, 30, 247, 170); // Viereck auf 80, 100 mit Seiten 20mm 20mm
Kreis zeichnen
pdf.circle( X, Y, radius, style); // style: S (default) für stroke, F für fill, DF oder FD Fill und Stroke
Bilder sind so’ne Sache
Bilder können data-URL-kodiert in das PDF gesetzt werden, dann liegen die Bilddaten vor, sobald die Seite geladen ist. Im Internet gibt es zahlreiche Seiten, die diese Umwandlung online durchführen, z.B. Convert your images to base64. Für Logos und kleine Bilder ist das die einfachste Lösung.
const imgData = getBase64Image(document.querySelector("#humpy img")); pdf.addImage(imgData,'JPEG',140,80,40,40);
Bye Bye Pixel – PDFs brauchen Zentimeter oder Millimeter. Durch die mm-Angaben von Breite und Höhe wird der Bereich für das Bild festgelegt. So könnte ein Bild auch mit 300dpi eingebracht werden – es muss nur im Bildbearbeitungsprogramm auf die entsprechende Größe berechnet werden.
Sind es mehrere und große Bilder oder kann der Benutzer Bilder auswählen, würden die langatmigen data-URLs die Seite überfrachten.
let img = new Image();
img.addEventListener("load", function() {
pdf.addImage(img, 'png', 20, 40, 40, 54);
| | | |
Position von links --+ | | |
Position von oben --+ | |
| |
Breite in mm --+ |
Höhe in mm --+
});
img.src = "image.png";
Dabei darf man eines nicht außer Acht lassen: Das Script wird fortgeführt, während der Event Listener auf das load-Event wartet. Folgt ein Seitenwechsel, würde das Bild auf der folgenden Seite landen. In so einem Fall springt z.B. eine Callback-Funktion ein.
/** https://davidwalsh.name/convert-image-data-uri-javascript **/
function getDataUri(url, callback) {
let image = new Image();
image.onload = function () {
callback();
};
image.src = url;
}
let url = "image.jpg";
getDataUri(url, function(dataUri) {
pdf.addImage(url,'JPEG', 20, 40, 40, 54,'', 'MEDIUM');
pdf.addPage(); // Um sicher zu gehen, dass das Bild
// ausgegeben wird.
});
Damit große Bilder nicht zu großen PDF-Dateien führen, werden sie besser komprimiert – das besorgt der letzte Parameter in pdf.addImage.
Die einfachsten Optionen sind None, Medium, Fast. Medium ist in den meisten Fällen gut genug, um ein 4MB PDF unter 1MB zu verkleinern.
Weitere Seiten hinzufügen
pdf.addPage() fügt dem PDF weitere Seiten hinzu.
Das sieht einfach aus, ist auch einfach.
pdf.internal.getNumberOfPages()
Fließtext
Fließtext ist genauso wie beim HTML-Canvas eben kein Fließtext. Einen Zeilenbruch oder Text zentrieren gibt es so erstmal nicht.
Allerdings es wäre viel zu mühsam, den Text Zeile für Zeile zu formatieren und zu setzen, und wenn der Text vom Benutzer erzeugt wird, muss er auf jeden Fall automatisch umgebrochen werden.
pdf.text ("Lorem ipsum es un texto pseudo-latino usedo en el diseño web, tipografía, layout, e", 25, 178); pdf.text ("imprenta a la vez del español para darle emphasís al diseño sobre el contenido.", 25, 183);
Für die Berechnung von Textabsätzen stellt jsPDF splitTextToSize bereit.
var loremipsum = "Lorem ipsum dolor adipiscing elit. … \n\nProin feugiat augue in augue rhoncus eu cursus tellus laoreet.";
var lines = pdf.setFontSize(11)
.splitTextToSize(loremipsum, 100);
│
Breite des Absatz –––┘
// left vertical margin
// | |
pdf.text(170, 33 + 11 / 100, lines);
│ │
font size –––┘ │
Absatzbreite –––┘
\n erzeugt einen Zeilenumbruch, \n\n einen Durchschuss zwischen zwei Absätzen.
Woher kommt das PDF?
Am Ende nicht vergessen, dem PDF die Adresse mitzugeben, von der es kam …
pdf.setLineWidth(1); pdf.line(25, 190, 270, 190); pdf.text ("PDF mit Javascript erzeugen: https://www.mediaevent.de/?p=5575", 25, 192);
Einen klickbaren Link setzen kann jsPDF nicht … jammerschade. Stattdessen gibt es Metadaten für das PDF und einen sprechenden Dateinamen.
pdf.setProperties({ title: 'PDF mit jsPDF erstellen', subject: 'PDF mit Javascript online zusammenstellen', author: 'U. Häßler', keywords: 'generated, javascript,jspdf', creator: 'Javascript jsPDF' }); pdf.save ("mediaevent.de/pdf-mit-javascipt.pdf");
Am Rand, aber keinesfalls nebensächlich: Add /Lang Setting plugin ist eine Voraussetzung für barrierefreies PDF (und inzwischen eingebaut).
Mehr zum PDF in Webseiten
- Anstandsregeln für PDFs in Webseiten – PDF wird zu oft benutzt, um sich das Erstellen von Webseiten zu sparen. Von der Lesbarkeit bis zur Barrierefreiheit schiebt PDF Berge von Stolpersteinen vor sich her.
- Bild mit Base64 einbetten – nicht nur interessant für PDFs, sondern spart bei kleinen Bildern einen weiteren HTTP-Request.
- Javascript Fetch Head Dateigröße von Bildern, ZIP-Archiven und PDF-Dokumenten ohne Laden der Dateien abfragen.