当前位置: 代码网 > it编程>前端脚本>Vue.js > vue前端实现导出页面为pdf(分页导出、不分页导出及分模块导出)

vue前端实现导出页面为pdf(分页导出、不分页导出及分模块导出)

2024年07月03日 Vue.js 我要评论
第一步:下载插件npm install --save html2canvas // 页面转图片npm install jspdf --save // 图片转pdf第

第一步:下载插件

npm install --save html2canvas       // 页面转图片
npm install jspdf --save             // 图片转pdf

第二步:main.js 文件引入

import htmltopdf from './utils/htmltopdf';
vue.use(htmltopdf);

第三步:utils/htmltopdf.js 文件中定义方法(有三种方法:分页导出、不分页导出、分模块导出;具体方法 见最下边)

第四步:vue页面调用方法 (htmltopdf)

方法一: 标准打印(分页打印);缺点:分页处会把内容给截断

export default {
  install(vue) {
    // eslint-disable-next-line func-names
    vue.prototype.htmltopdf = function (ele, title) {
      const dom = document.queryselector('#' + ele)
      html2canvas(dom, {
        usecors: true,//解决网络图片跨域问题
        width: dom.width,
        height: dom.height,
        windowwidth: dom.scrollwidth,
        dpi: window.devicepixelratio * 4, // 将分辨率提高到特定的dpi 提高四倍
        scale: 4, // 按比例增加分辨率
      }).then((canvas) => {
        // eslint-disable-next-line new-cap
        const pdf = new jspdf('p', 'mm', 'a4'); // a4纸,纵向
        const ctx = canvas.getcontext('2d');
        const a4w = 170; 
        const a4h = 250; // a4大小,210mm x 297mm,四边各保留20mm的边距,显示区域170x257
        const imgheight = math.floor(a4h * canvas.width / a4w); // 按a4显示比例换算一页图像的像素高度
        let renderedheight = 0;
 
        while (renderedheight < canvas.height) {
          const page = document.createelement('canvas');
          page.width = canvas.width;
          page.height = math.min(imgheight, canvas.height - renderedheight);// 可能内容不足一页
 
          // 用getimagedata剪裁指定区域,并画到前面创建的canvas对象中
          page.getcontext('2d').putimagedata(ctx.getimagedata(0, renderedheight, canvas.width, math.min(imgheight, canvas.height - renderedheight)), 0, 0);
          pdf.addimage(page.todataurl('image/jpeg', 1.0), 'jpeg', 20, 20, a4w, math.min(a4h, a4w * page.height / page.width)); // 添加图像到页面,保留10mm边距
 
          renderedheight += imgheight;
          if (renderedheight < canvas.height) {
            pdf.addpage();// 如果后面还有内容,添加一个空页
          }
          // 预览pdf(这里我用的是事件总线把canvas传递过去展示,达到模拟pdf预览的效果,有用但效果不是很好,有需要的可以自行修改)
          //this.$eventbus.$emit('open-pdf', canvas);
        }
        // 保存文件
        pdf.save(`${title}.pdf`);
      });
    };
  },
}

方法二: 标准打印(不分页打印)

export default {
  install(vue) {
    vue.prototype.htmltopdf = function (name, title) {
      html2canvas(document.queryselector('#' + name), {
        // allowtaint: true,
        usecors: true,
        scale: 2, // 提升画面质量,但是会增加文件大小
        dpi: window.devicepixelratio * 1,
      }).then((canvas) => {
        const contentwidth = canvas.width
        const contentheight = canvas.height
         
         /* 导出不分页处理 */
        const pagedata = canvas.todataurl('image/jpeg', 1.0)

        const pdfwidth = (contentwidth + 10) / 2 * 0.75
        const pdfheight = (contentheight + 200) / 2 * 0.75 // 500为底部留白

        const imgwidth = pdfwidth
        const imgheight = (contentheight / 2 * 0.75) // 内容图片这里不需要留白的距离

        const pdf = new jspdf('', 'pt', [ pdfwidth + 50, pdfheight + 100, ])
        pdf.addimage(pagedata, 'jpeg', 33, 33, imgwidth, imgheight)
        pdf.save(title + '.pdf')
      })
    };
  },
}

方法三: 分模块打印(一个模块一个页面)

export default {
  install(vue) {
    vue.prototype.htmltopdf = async function (name, title) {
      const ele = document.queryselector('#' + name)
      const elew = ele.offsetwidth// 获得该容器的宽
      const eleh = ele.offsetheight// 获得该容器的高
    
      const eleoffsettop = ele.offsettop // 获得该容器到文档顶部的距离
      const eleoffsetleft = ele.offsetleft // 获得该容器到文档最左的距离
    
      var canvas = document.createelement('canvas')
      var abs = 0
    
      const win_in = document.documentelement.clientwidth || document.body.clientwidth // 获得当前可视窗口的宽度(不包含滚动条)
      const win_out = window.innerwidth // 获得当前窗口的宽度(包含滚动条)
    
      if (win_out > win_in) {
        // abs = (win_o - win_i)/2;    // 获得滚动条长度的一半
        abs = (win_out - win_in) / 2 // 获得滚动条宽度的一半
        // console.log(a, '新abs');
      }
    
      canvas.width = elew * 2 // 将画布宽&&高放大两倍
      canvas.height = eleh * 2
    
      var context = canvas.getcontext('2d')
    
      context.scale(2, 2)
    
      context.translate(-eleoffsetleft - abs, -eleoffsettop)
      // 这里默认横向没有滚动条的情况,因为offset.left(),有无滚动条的时候存在差值,因此
      // translate的时候,要把这个差值去掉
    
      var pdf = new jspdf('', 'pt', 'a4')
      const childrenbox = ele.children
      for (let i = 0; i < childrenbox.length; i++) { // 循环传过来的dom的字节点 每个子节点打印成一页pdf a4纸那么大
        console.log(childrenbox,'childrenbox');
        console.log(1111);
        const res = await html2canvas(childrenbox[i], {
          dpi: 300,
          // allowtaint: true,  //允许 canvas 污染, allowtaint参数要去掉,否则是无法通过todataurl导出canvas数据的
          usecors: true, // 允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
          scale: 4, // 提升导出的文件的分辨率
        })
        var pagedata = res.todataurl('image/jpeg', 1.0)
        var contentwidth = res.width
        var contentheight = res.height
        var imgwidth = 555.28
        var imgheight = 552.28 / contentwidth * contentheight
        pdf.addimage(pagedata, 'jpeg', 20, 20, imgwidth, imgheight)
        if (i < childrenbox.length - 1) {
          pdf.addpage() // 避免最后多一个空白页
        }
      }

      pdf.save(`${title}.pdf`);
    };
  },
}

总结 

到此这篇关于vue前端实现导出页面为pdf的文章就介绍到这了,更多相关vue前端导出页面pdf内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com