前端 HTML 转 PDF
spdf两个库转换成 PDF 文件并下载到本地。简单说它能让用户 “一键下载” 网页上的某个区域为 PDF比如报表、数据统计页、合同预览页等还预留了 “水印功能” 的注释代码可按需启用。核心依赖说明函数依赖两个关键库必须先安装才能使用函数核心逻辑分步拆解函数名htmlToPdf接收两个参数title下载的 PDF 文件名比如 “2024 年报表”htmlId需要转换的 HTML 元素的 ID比如#report-container。整体流程定位 HTML 元素 → 滚动置顶避免截图不全 → 可选加水印→ HTML 转 Canvas → Canvas 转 PDF → 下载 PDF1. 准备工作定位元素 滚动置顶12345constelement document.querySelector(htmlId);// 找到要转PDF的HTML元素// 滚动置顶避免元素被滚动条遮挡导致截图不全window.pageYOffset 0;document.documentElement.scrollTop 0;document.body.scrollTop 0;2. 可选添加水印已注释需启用可取消注释注释部分的逻辑是创建一个带文字水印比如 “我是水印”的 Canvas作为背景图添加到目标元素上转 PDF 时水印会一起被截取适合需要版权保护的场景。3. HTML 转 Canvas核心步骤123456789html2Canvas(element, {allowTaint:true,// 允许跨域图片如果元素内有跨域图片需开启useCORS:true,// 启用CORS跨域支持scale: 2,// 缩放2倍提升PDF清晰度代价是文件变大height: element.scrollHeight,// 用元素实际滚动高度避免只截取可视区域关键windowHeight: element.scrollHeight}).then(canvas {// Canvas生成成功后进入PDF生成步骤});4. Canvas 转 PDF 并下载123456789101112131415161718192021222324252627constcontentWidth canvas.width;// Canvas宽度constcontentHeight canvas.height;// Canvas高度constpageHeight (contentWidth * 841.89) / 592.28;// A4纸的高度按比例计算letleftHeight contentHeight;// 未生成PDF的剩余高度letposition 0;// PDF页面偏移量// 创建A4尺寸的PDF纵向p portraitconstpdf newJsPDF(p,pt,a4);// Canvas转成图片数据jpeg格式质量1.0constpageData canvas.toDataURL(image/jpeg, 1.0);// 处理分页如果内容高度超过1页A4纸自动分页if(leftHeight pageHeight) {// 单页直接嵌入图片20是左右边距避免内容贴边pdf.addImage(pageData,JPEG, 20, 20, imgWidth, imgHeight);}else{// 多页循环截取内容每满1页添加新页面while(leftHeight 0) {pdf.addImage(pageData,JPEG, 20, position, imgWidth, imgHeight);leftHeight - pageHeight;position - 841.89;// 向下偏移A4纸高度if(leftHeight 0) pdf.addPage();// 剩余内容不为空时新增一页}}// 触发下载文件名title.pdfpdf.save(title .pdf);如何使用1. 安装依赖12345# npm 安装npm install html2canvas jspdf --save# pnpm 安装pnpm add html2canvas jspdf2.创建一个htmlToPdf.js文件12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879import html2Canvasfromhtml2canvas;import JsPDFfromjspdf;// title:下载文件的名称 htmlId:包裹的标签的idconsthtmlToPdf (title, htmlId) {constelement document.querySelector(htmlId);window.pageYOffset 0;document.documentElement.scrollTop 0;document.body.scrollTop 0;setTimeout(() {// // 以下注释的是增加导出的pdf水印 // const value 我是水印// //创建一个画布// let can document.createElement(canvas)// //设置画布的长宽// can.width 400// can.height 500// let cans can.getContext(2d) as any// //旋转角度// cans.rotate((-15 * Math.PI) / 180)// cans.font 18px Vedana// //设置填充绘画的颜色、渐变或者模式// cans.fillStyle rgba(200, 200, 200, 0.40)// //设置文本内容的当前对齐方式// cans.textAlign left// //设置在绘制文本时使用的当前文本基线// cans.textBaseline Middle// //在画布上绘制填色的文本输出的文本开始绘制文本的X坐标位置开始绘制文本的Y坐标位置// cans.fillText(value, can.width / 8, can.height / 2)// let div document.createElement(div)// div.style.pointerEvents none// div.style.top 20px// div.style.left -20px// div.style.position fixed// div.style.zIndex 100000// div.style.width element.scrollHeight px// div.style.height element.scrollHeight px// div.style.background // url( can.toDataURL(image/png) ) left top repeat// element.appendChild(div) // 到页面中html2Canvas(element, {allowTaint:true,useCORS:true,scale: 2,// 提升画面质量但是会增加文件大小height: element.scrollHeight,// 需要注意element的 高度 宽度一定要在这里定义一下不然会存在只下载了当前你能看到的页面 避雷避雷windowHeight: element.scrollHeight}).then(function (canvas) {constcontentWidth canvas.width;constcontentHeight canvas.height;// 一页pdf显示html页面生成的canvas高度;constpageHeight (contentWidth * 841.89) / 592.28;// 未生成pdf的html页面高度letleftHeight contentHeight;// 页面偏移letposition 0;// a4纸的尺寸[595.28,841.89]html页面生成的canvas在pdf中图片的宽高 //40是左右页边距constimgWidth 595.28 - 40;constimgHeight (592.28 / contentWidth) * contentHeight;constpageData canvas.toDataURL(image/jpeg, 1.0);constpdf newJsPDF(p,pt,a4);// 有两个高度需要区分一个是html页面的实际高度和生成pdf的页面高度(841.89)// 当内容未超过pdf一页显示的范围无需分页if(leftHeight pageHeight) {pdf.addImage(pageData,JPEG, 20, 20, imgWidth, imgHeight);}else{while(leftHeight 0) {pdf.addImage(pageData,JPEG, 20, position, imgWidth, imgHeight);leftHeight - pageHeight;position - 841.89;// 避免添加空白页if(leftHeight 0) {pdf.addPage();}}}pdf.save(title .pdf);});}, 1000);};exportdefaulthtmlToPdf;3. 在 Vue/React 中使用示例12345678910111213141516171819202122232425!-- Vue 示例页面中有一个要转PDF的区域 --templatediv!-- 要转PDF的元素必须有唯一ID --div idreport-containerh12024年销售报表/h1table.../table !-- 报表内容 --/div!-- 下载按钮 --button clickdownloadPdf下载PDF/button/div/templatescriptimport htmlToPdffrom/utils/htmlToPdf;// 导入函数exportdefault{methods: {downloadPdf() {// 调用函数参数1PDF文件名参数2目标元素ID注意加#htmlToPdf(2024年销售报表,#report-container);}}}/script常见问题与优化1. 截图不全 / 内容缺失确保目标元素的height/scrollHeight正确函数已处理但如果元素是动态渲染的可能需要调整setTimeout延迟时间比如从 1000ms 改为 2000ms避免元素内有position: fixed的内容会被重复截取。2. 图片跨域导致截图空白确保html2Canvas配置中allowTaint: true和useCORS: true已开启图片服务器需配置 CORS 允许当前域名访问。3. PDF 清晰度太低增大scale参数比如改为 3但会导致文件变大把toDataURL的质量参数从 1.0 保留已最优。4. 想要启用水印取消代码中水印相关的注释修改value为你的水印文字比如 “内部资料”调整rotate旋转角度、font字体大小、fillStyle透明度0.4 为半透明。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2473250.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!