import html2canvas from 'html2canvas'; import { jsPDF } from 'jspdf'; export interface Options { filename?: string; compress?: boolean; scale?: number; callback?: () => void; } const noop = () => {}; export async function exportPdf( element: HTMLElement | null, options: Options = {}, ): Promise<void> { const { filename = '未命名', compress = true, scale = 2, callback = noop, } = options; if (!element) { callback(); return; } const originWidth = element.offsetWidth || 700; const container = document.createElement('div'); container.style.cssText = `position:fixed;left:${-2 * originWidth}px;top:0;padding:0px;width:${originWidth}px;box-sizing:content-box;`; document.body.appendChild(container); container.appendChild(element.cloneNode(true)); const render = async () => { try { const canvas = await html2canvas(container, { scale }); const contentWidth = canvas.width; const contentHeight = canvas.height; // 一页全部展示 // eslint-disable-next-line new-cap const doc = new jsPDF({ orientation: contentWidth > contentHeight ? 'l' : 'p', unit: 'px', format: [contentWidth, contentHeight], compress, }); doc.addImage({ imageData: canvas, format: 'PNG', x: 0, y: 0, width: contentWidth, height: contentHeight, compression: 'FAST', }); doc.save(`${filename}.pdf`); } catch (error) { console.error(`Error rendering PDF:`, error); } finally { container.remove(); callback(); } }; const eleImgs = Array.from(container.querySelectorAll('img')); const { length } = eleImgs; let start = 0; if (length === 0) { await render(); return; } eleImgs.forEach((ele) => { const { src } = ele; if (!src) return; ele.onload = () => { if (!/^http/.test(ele.src)) { start++; if (start === length) { render(); } } }; fetch(src) .then((res) => res.blob()) .then((blob) => { const reader = new FileReader(); reader.onload = () => { ele.src = reader.result as string; }; reader.readAsDataURL(blob); return true; }) .catch((error) => { start++; console.error(`Error fetching image:`, error); if (start === length) { render(); } }); }); }