fix: robust per-card PDF export to avoid blank pages
This commit is contained in:
@@ -73,6 +73,8 @@ body.modal-open { overflow: hidden; }
|
|||||||
<link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" />
|
<link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" />
|
||||||
<script src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
|
<script src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
||||||
</head><body>
|
</head><body>
|
||||||
<div class="topbar">
|
<div class="topbar">
|
||||||
<button id="menuToggle" class="menu-btn">☰</button>
|
<button id="menuToggle" class="menu-btn">☰</button>
|
||||||
@@ -496,44 +498,61 @@ function closeAiModal(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function downloadPdf(){
|
async function downloadPdf(){
|
||||||
if (!window.html2pdf) {
|
if (!window.html2canvas || !window.jspdf?.jsPDF) {
|
||||||
alert('PDF-Export-Bibliothek nicht geladen.');
|
alert('PDF-Export-Bibliothek nicht geladen.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const root = document.createElement('div');
|
const root = document.createElement('div');
|
||||||
root.style.position = 'fixed';
|
root.style.position = 'fixed';
|
||||||
root.style.left = '0';
|
root.style.left = '-10000px';
|
||||||
root.style.top = '0';
|
root.style.top = '0';
|
||||||
root.style.width = '210mm';
|
root.style.width = '1200px';
|
||||||
root.style.minHeight = '297mm';
|
|
||||||
root.style.background = '#fff';
|
root.style.background = '#fff';
|
||||||
root.style.padding = '8mm';
|
|
||||||
root.style.zIndex = '-1';
|
|
||||||
root.style.opacity = '0.01';
|
|
||||||
root.style.pointerEvents = 'none';
|
|
||||||
root.innerHTML = app.innerHTML;
|
root.innerHTML = app.innerHTML;
|
||||||
|
|
||||||
root.querySelectorAll('.card-actions,.card-action-btn,button,[data-edit-all]').forEach(el => el.remove());
|
root.querySelectorAll('.card-actions,.card-action-btn,button,[data-edit-all]').forEach(el => el.remove());
|
||||||
root.querySelectorAll('.exercise-container').forEach(el => { el.style.pageBreakAfter = 'always'; });
|
|
||||||
root.querySelectorAll('.card-size').forEach(el => {
|
root.querySelectorAll('.card-size').forEach(el => {
|
||||||
el.style.boxShadow = 'none';
|
el.style.boxShadow = 'none';
|
||||||
el.style.margin = '0 auto 10mm auto';
|
el.style.margin = '0 0 12px 0';
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.appendChild(root);
|
document.body.appendChild(root);
|
||||||
|
|
||||||
const opt = {
|
|
||||||
margin: [5, 5, 5, 5],
|
|
||||||
filename: `coachingcards-${new Date().toISOString().slice(0,10)}.pdf`,
|
|
||||||
image: { type: 'jpeg', quality: 0.98 },
|
|
||||||
html2canvas: { scale: 2, useCORS: true, backgroundColor: '#ffffff', logging: false },
|
|
||||||
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' },
|
|
||||||
pagebreak: { mode: ['css', 'legacy'] }
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await window.html2pdf().set(opt).from(root).save();
|
const cards = [...root.querySelectorAll('.card-size')];
|
||||||
|
if (!cards.length) {
|
||||||
|
alert('Keine Karten für den Export sichtbar.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { jsPDF } = window.jspdf;
|
||||||
|
const pdf = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });
|
||||||
|
const pageW = pdf.internal.pageSize.getWidth();
|
||||||
|
const pageH = pdf.internal.pageSize.getHeight();
|
||||||
|
const margin = 8;
|
||||||
|
const usableW = pageW - margin * 2;
|
||||||
|
const usableH = pageH - margin * 2;
|
||||||
|
|
||||||
|
for (let i = 0; i < cards.length; i++) {
|
||||||
|
const canvas = await window.html2canvas(cards[i], {
|
||||||
|
scale: 2,
|
||||||
|
useCORS: true,
|
||||||
|
backgroundColor: '#ffffff',
|
||||||
|
logging: false
|
||||||
|
});
|
||||||
|
const img = canvas.toDataURL('image/jpeg', 0.98);
|
||||||
|
const imgW = canvas.width;
|
||||||
|
const imgH = canvas.height;
|
||||||
|
const ratio = Math.min(usableW / imgW, usableH / imgH);
|
||||||
|
const drawW = imgW * ratio;
|
||||||
|
const drawH = imgH * ratio;
|
||||||
|
const x = margin + (usableW - drawW) / 2;
|
||||||
|
const y = margin + (usableH - drawH) / 2;
|
||||||
|
|
||||||
|
if (i > 0) pdf.addPage();
|
||||||
|
pdf.addImage(img, 'JPEG', x, y, drawW, drawH, undefined, 'FAST');
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf.save(`coachingcards-${new Date().toISOString().slice(0,10)}.pdf`);
|
||||||
} finally {
|
} finally {
|
||||||
root.remove();
|
root.remove();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user