vue生成pdf文件步骤及pdf分页隔断处理方法

2024-03-01 0 202
目录
  • 一:PDF生成步骤
    • 1.1 引入所需插件命令
    • 1.2 在utils中创建pdf.js文件
    • 1.3 html文件
    • 1.4 生成演示
  • 二:PDF分页隔断处理
    • 2.1 html代码
    • 2.2 pdf.js文件
    • 2.3 效果
  • 总结

    一:PDF生成步骤

    1.1 引入所需插件命令

    npm install html2canvas

    npm install jspdf

    1.2 在utils中创建pdf.js文件

    pdf.js完整代码

    // 页面导出为pdf格式 //title表示为下载的标题,html表示document.querySelector(\’#myPrintHtml\’)
    import html2Canvas from \’html2canvas\’;
    import JsPDF from \’jspdf\’;
    function htmlPdf(title, html) {
    html2Canvas(html, {
    allowTaint: false,
    taintTest: false,
    logging: false,
    useCORS: true,
    dpi: window.devicePixelRatio * 1,
    scale: 1 // 按比例增加分辨率
    }).then(canvas => {
    var pdf = new JsPDF(\’p\’, \’mm\’, \’a4\’); // A4纸,纵向
    var ctx = canvas.getContext(\’2d\’);
    var a4w = 190; var a4h = 277; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190×277
    var imgHeight = Math.floor(a4h * canvas.width / a4w); // 按A4显示比例换算一页图像的像素高度
    var renderedHeight = 0;
    while (renderedHeight < canvas.height) {
    var 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\’, 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)); // 添加图像到页面,保留10mm边距

    renderedHeight += imgHeight;
    if (renderedHeight < canvas.height) {
    pdf.addPage();// 如果后面还有内容,添加一个空页
    }
    // delete page;
    }
    // 保存文件
    pdf.save(title + \’.pdf\’);
    });
    }

    export default htmlPdf;

    1.3 html文件

    html完整代码

    <template>
    <div>
    <button @click=\”generate\”>点击按钮导出pdf</button>
    <div id=\”pdf-details\” class=\”pdf-details\”>
    <h1>div里写需要生成的PDF内容的代码</h1>
    <table border=\”1\” align=\”center\” cellspacing=\”0\” cellpadding=\”30\”>
    <tr class=\”pdf-details\”>
    <th style=\”width:80px\”>日期</th>
    <th style=\”width:100px\”>姓名</th>
    <th>地址</th>
    </tr>
    <tr v-for=\”(item,index) in tableData\” :key=\”index\” class=\”pdf-details\”>
    <td>{{item.date}}</td>
    <td>{{item.name}}</td>
    <td>{{item.address}}</td>
    </tr>
    </table>
    </div>
    </div>
    </template>
    <script>
    import htmlPdf from \’@/utils/pdf.js\’;
    export default {
    name: \’pdfGenerate\’,
    data () {
    return {
    tableData: [
    {date: \’2016-05-02\’,name: \’王大虎\’,address: \’上海市普陀区金沙江路 111 弄\’},
    {date: \’2016-05-04\’,name: \’王二虎\’,address: \’上海市普陀区金沙江路 112 锤\’},
    {date: \’2016-05-01\’,name: \’王三虎\’,address: \’上海市普陀区金沙江路 113 子\’},
    {date: \’2016-05-03\’,name: \’王四虎\’,address: \’上海市普陀区金沙江路 114 呢\’},
    {date: \’2016-05-03\’,name: \’王没虎\’,address: \’上海市普陀区金沙江路 110 弄\’}
    ]
    }
    },
    methods: {
    generate () {
    var TypeName = \’生成的PDF\’;
    // 注意这一句
    htmlPdf(TypeName, document.querySelector(\’#pdf-details\’));
    }
    }
    }
    </script>

    1.4 生成演示

    vue生成pdf文件步骤及pdf分页隔断处理方法

    二:PDF分页隔断处理

    • 在我们日常开发中生成pdf会遇到内容显示出现隔断问题
    • 接下来我会通过代码来处理这个问题

      vue生成pdf文件步骤及pdf分页隔断处理方法

    • 思路为获取每一行的高度然后根据页高度来计算此行内容是否超出
    • 超出则在上一级兄弟元素添加一个空白块来撑高pad内容

    2.1 html代码

    • 需要生成的pdf每一行添加一个相同的class作为标识,此次增加的class为“pdf-details”
    • 调用htmlPdf方法时需要获取class为“pdf-details”的元素传给pdf.js

    html完整代码

    <template>
    <div>
    <button @click=\”generate\”>点击按钮导出pdf</button>
    <div id=\”pdf-details\” >
    <h1 class=\”pdf-details\” style=\”margin:0;padding:20px\”>div里写需要生成的PDF内容的代码</h1>
    <div class=\”pdf-details\” style=\”height:495px\”>占位</div>
    <table border=\”1\” align=\”center\” cellspacing=\”0\” cellpadding=\”30\”>
    <tr class=\”pdf-details\”>
    <th style=\”width:80px\”>日期</th><th style=\”width:100px\”>姓名</th><th>地址</th>
    </tr>
    <tr v-for=\”(item,index) in tableData\” :key=\”index\” class=\”pdf-details\”>
    <td>{{item.date}}</td><td>{{item.name}}</td><td>{{item.address}}</td>
    </tr>
    </table>
    </div>
    </div>
    </template>
    <script>
    //引用生成pdf方法
    import htmlPdf from \’@/utils/pdf.js\’;
    export default {
    name: \’pdfGenerate\’,
    data () {
    return {
    tableData: [
    {date: \’2016-05-02\’,name: \’王大虎\’,address: \’上海市普陀区金沙江路 111 弄\’},
    {date: \’2016-05-04\’,name: \’王二虎\’,address: \’上海市普陀区金沙江路 112 锤\’},
    {date: \’2016-05-01\’,name: \’王三虎\’,address: \’上海市普陀区金沙江路 113 子\’},
    {date: \’2016-05-03\’,name: \’王四虎\’,address: \’上海市普陀区金沙江路 114 呢\’},
    {date: \’2016-05-03\’,name: \’测试超长隔断\’,address: \’这是汉字但生成时有隔断,我现在要处理他;这是汉字但生成时有隔断,我现在要处理他;\’},
    {date: \’2016-05-03\’,name: \’王没虎\’,address: \’上海市普陀区金沙江路 110 弄\’},
    {date: \’2016-05-03\’,name: \’王没虎\’,address: \’上海市普陀区金沙江路 110 啊\’},
    {date: \’2016-05-03\’,name: \’王没虎\’,address: \’上海市普陀区金沙江路 110 测\’},
    {date: \’2016-05-03\’,name: \’王没虎\’,address: \’上海市普陀区金沙江路 110 试\’}
    ]
    }
    },
    methods: {
    generate () {
    var TypeName = \’生成的PDF\’;
    const lableList = document.getElementsByClassName(\’pdf-details\’); // 注意这一句
    htmlPdf(TypeName, document.querySelector(\’#pdf-details\’), lableList);
    }
    }
    }
    </script>
    <style>
    td{
    padding: 20px;
    }
    </style>

    2.2 pdf.js文件

    • 首先获取每一行需要生成的元素来进行遍历
    • 根据当前元素以及遍历过的元素总高度来计算出当前元素添加到pdf中是否超出一页
    • 超出则添加一个空白块 代替当前元素 当前元素移动到第二页

    pdf.js完整代码

    // 页面导出为pdf格式 //title表示为下载的标题,html表示document.querySelector(\’#myPrintHtml\’)
    import html2Canvas from \’html2canvas\’;
    import JsPDF from \’jspdf\’;
    var noTableHeight = 0; //table外的元素高度
    function htmlPdf(title, html, lableList, type) {// type传有效值pdf则为横版
    if (lableList) {
    const pageHeight = Math.floor(277 * html.scrollWidth / 190) +20; //计算pdf高度
    for (let i = 0; i < lableList.length; i++) { //循环获取的元素
    const multiple = Math.ceil((lableList[i].offsetTop + lableList[i].offsetHeight) / pageHeight); //元素的高度
    if (isSplit(lableList, i, multiple * pageHeight)) { //计算是否超出一页
    var _H = \’\’ //向pdf插入空白块的内容高度
    if(lableList[i].localName !== \’tr\’){ //判断是不是表格里的内容
    _H = multiple * pageHeight – (lableList[i].offsetTop + lableList[i].offsetHeight);
    }else{
    _H = multiple * pageHeight – (lableList[i].offsetTop + lableList[i].offsetHeight + noTableHeight) +20;
    }
    var newNode = getFooterElement(_H); //向pdf插入空白块的内容
    const divParent = lableList[i].parentNode; // 获取该div的父节点
    const next = lableList[i].nextSibling; // 获取div的下一个兄弟节点
    // 判断兄弟节点是否存在
    if (next) {
    // 存在则将新节点插入到div的下一个兄弟节点之前,即div之后
    divParent.insertBefore(newNode, next);
    } else {
    // 否则向节点添加最后一个子节点
    divParent.appendChild(newNode);
    }
    }
    }
    }
    html2Canvas(html, {
    allowTaint: false,
    taintTest: false,
    logging: false,
    useCORS: true,
    dpi: window.devicePixelRatio * 1,
    scale: 1 // 按比例增加分辨率
    }).then(canvas => {
    var pdf = new JsPDF(\’p\’, \’mm\’, \’a4\’); // A4纸,纵向
    var ctx = canvas.getContext(\’2d\’);
    var a4w = type ? 277 : 190; var a4h = type ? 190 : 277; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190×277
    var imgHeight = Math.floor(a4h * canvas.width / a4w); // 按A4显示比例换算一页图像的像素高度
    var renderedHeight = 0;
    while (renderedHeight < canvas.height) {
    var 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\’, 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)); // 添加图像到页面,保留10mm边距

    renderedHeight += imgHeight;
    if (renderedHeight < canvas.height) {
    pdf.addPage();// 如果后面还有内容,添加一个空页
    }
    // delete page;
    }
    // 保存文件
    pdf.save(title + \’.pdf\’);
    });
    }
    // pdf截断需要一个空白位置来补充
    function getFooterElement(remainingHeight, fillingHeight = 0) {
    const newNode = document.createElement(\’div\’);
    newNode.style.background = \’#ffffff\’;
    newNode.style.width = \’calc(100% + 8px)\’;
    newNode.style.marginLeft = \’-4px\’;
    newNode.style.marginBottom = \’0px\’;
    newNode.classList.add(\’divRemove\’);
    newNode.style.height = (remainingHeight + fillingHeight) + \’px\’;
    return newNode;
    }
    function isSplit(nodes, index, pageHeight) {
    // 判断是不是tr 如果不是高度存起来
    // 表格里的内容要特殊处理
    // tr.offsetTop 是tr到table表格的高度
    // 所以计算高速时候要把表格外的高度加起来
    // 生成的pdf没有表格了这里可以不做处理 直接计算就行
    if(nodes[index].localName !== \’tr\’){ //判断元素是不是tr
    noTableHeight+= nodes[index].clientHeight
    }

    if(nodes[index].localName !== \’tr\’){
    return nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight;
    } else {
    return nodes[index].offsetTop + nodes[index].offsetHeight + noTableHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight + noTableHeight > pageHeight;
    }
    }
    export default htmlPdf;

    2.3 效果

    vue生成pdf文件步骤及pdf分页隔断处理方法

    总结

    到此这篇关于vue生成pdf文件步骤及pdf分页隔断处理方法的文章就介绍到这了,更多相关vue生成pdf及分页隔断内容请搜索悠久资源网以前的文章或继续浏览下面的相关文章希望大家以后多多支持悠久资源网!

    您可能感兴趣的文章:

    • Vue页面生成PDF的最佳方法推荐
    • vue-pdf插件实现pdf文档预览方式(自动分页预览)
    • vue3将页面生成pdf导出的操作指南

    收藏 (0) 打赏

    感谢您的支持,我会继续努力的!

    打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
    点赞 (0)

    悠久资源 JavaScript vue生成pdf文件步骤及pdf分页隔断处理方法 https://www.u-9.cn/biancheng/javascript/182204.html

    常见问题

    相关文章

    发表评论
    暂无评论
    官方客服团队

    为您解决烦忧 - 24小时在线 专业服务