Simplify PDF export using jsPDF's html() method for automatic pagination
- Removed complex manual page-by-page rendering logic - Using jsPDF's built-in html() method instead (like dompdf does) - Handles pagination automatically with proper page breaks - Set 20mm margins on all sides via margin parameter - Content width set to 170mm (210mm - 40mm margins) - Much simpler and more reliable approach - Leverages jsPDF's native HTML rendering engine
This commit is contained in:
@@ -153,28 +153,8 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges }: N
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create PDF
|
// Create a container with title and content
|
||||||
const pdf = new jsPDF({
|
|
||||||
orientation: 'portrait',
|
|
||||||
unit: 'mm',
|
|
||||||
format: 'a4',
|
|
||||||
});
|
|
||||||
|
|
||||||
const pageWidth = 210; // A4 width in mm
|
|
||||||
const pageHeight = 297; // A4 height in mm
|
|
||||||
const margin = 20; // 20mm margins on all sides
|
|
||||||
const contentWidth = pageWidth - (2 * margin); // 170mm
|
|
||||||
const contentHeight = pageHeight - (2 * margin); // 257mm
|
|
||||||
|
|
||||||
// Create a temporary container with proper page dimensions
|
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.style.width = `${contentWidth}mm`;
|
|
||||||
container.style.minHeight = `${contentHeight}mm`;
|
|
||||||
container.style.padding = '0';
|
|
||||||
container.style.backgroundColor = 'white';
|
|
||||||
container.style.position = 'absolute';
|
|
||||||
container.style.left = '-9999px';
|
|
||||||
container.style.top = '0';
|
|
||||||
container.style.fontFamily = 'Arial, sans-serif';
|
container.style.fontFamily = 'Arial, sans-serif';
|
||||||
container.style.fontSize = '12px';
|
container.style.fontSize = '12px';
|
||||||
container.style.lineHeight = '1.6';
|
container.style.lineHeight = '1.6';
|
||||||
@@ -197,63 +177,19 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges }: N
|
|||||||
contentClone.style.color = '#000000';
|
contentClone.style.color = '#000000';
|
||||||
container.appendChild(contentClone);
|
container.appendChild(contentClone);
|
||||||
|
|
||||||
document.body.appendChild(container);
|
// Create PDF using jsPDF's html() method (like dompdf)
|
||||||
|
const pdf = new jsPDF({
|
||||||
// Get the total height of content
|
orientation: 'portrait',
|
||||||
const totalHeight = container.scrollHeight;
|
unit: 'mm',
|
||||||
const pixelsPerMm = container.offsetWidth / contentWidth;
|
format: 'a4',
|
||||||
const contentHeightPx = contentHeight * pixelsPerMm;
|
|
||||||
|
|
||||||
// Calculate number of pages needed
|
|
||||||
const numPages = Math.ceil(totalHeight / contentHeightPx);
|
|
||||||
|
|
||||||
// Render each page separately
|
|
||||||
for (let pageNum = 0; pageNum < numPages; pageNum++) {
|
|
||||||
// Create a wrapper for this page's content
|
|
||||||
const pageWrapper = document.createElement('div');
|
|
||||||
pageWrapper.style.width = `${contentWidth}mm`;
|
|
||||||
pageWrapper.style.height = `${contentHeight}mm`;
|
|
||||||
pageWrapper.style.overflow = 'hidden';
|
|
||||||
pageWrapper.style.position = 'absolute';
|
|
||||||
pageWrapper.style.left = '-9999px';
|
|
||||||
pageWrapper.style.top = '0';
|
|
||||||
pageWrapper.style.backgroundColor = 'white';
|
|
||||||
|
|
||||||
// Clone the container and position it to show only this page's content
|
|
||||||
const pageContent = container.cloneNode(true) as HTMLElement;
|
|
||||||
pageContent.style.position = 'relative';
|
|
||||||
pageContent.style.top = `-${pageNum * contentHeightPx}px`;
|
|
||||||
pageWrapper.appendChild(pageContent);
|
|
||||||
|
|
||||||
document.body.appendChild(pageWrapper);
|
|
||||||
|
|
||||||
// Render this page to canvas
|
|
||||||
const canvas = await html2canvas(pageWrapper, {
|
|
||||||
scale: 2,
|
|
||||||
useCORS: true,
|
|
||||||
backgroundColor: '#ffffff',
|
|
||||||
width: pageWrapper.offsetWidth,
|
|
||||||
height: pageWrapper.offsetHeight,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove the page wrapper
|
// Use jsPDF's html() method which handles pagination automatically
|
||||||
document.body.removeChild(pageWrapper);
|
await pdf.html(container, {
|
||||||
|
callback: async (doc) => {
|
||||||
// Add page to PDF (add new page if not first)
|
|
||||||
if (pageNum > 0) {
|
|
||||||
pdf.addPage();
|
|
||||||
}
|
|
||||||
|
|
||||||
const imgData = canvas.toDataURL('image/png');
|
|
||||||
pdf.addImage(imgData, 'PNG', margin, margin, contentWidth, contentHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the original container
|
|
||||||
document.body.removeChild(container);
|
|
||||||
|
|
||||||
// Save the PDF
|
// Save the PDF
|
||||||
const fileName = `${localTitle || 'note'}.pdf`;
|
const fileName = `${localTitle || 'note'}.pdf`;
|
||||||
pdf.save(fileName);
|
doc.save(fileName);
|
||||||
|
|
||||||
// Show success message using Tauri dialog
|
// Show success message using Tauri dialog
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
@@ -267,6 +203,13 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges }: N
|
|||||||
}
|
}
|
||||||
setIsExportingPDF(false);
|
setIsExportingPDF(false);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
},
|
||||||
|
x: 20, // 20mm left margin
|
||||||
|
y: 20, // 20mm top margin
|
||||||
|
width: 170, // 170mm content width (210 - 40)
|
||||||
|
windowWidth: 800, // Rendering width in pixels
|
||||||
|
margin: [20, 20, 20, 20], // top, right, bottom, left margins in mm
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('PDF export failed:', error);
|
console.error('PDF export failed:', error);
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user