vue2利用html2canvas+jspdf动态生成多页PDF

业务需求中,前端把页面上的内容导出为图片,pdf,excel是常有的事。当然,这些工作后端也是能做。秉着前端是万能的理念,今天就站在前端的角度上,来实现将页面内容导出为pdf,实现指定div内容导出,并自动拼接成一个多页的PDF文件

1.PDF相关依赖

vue2脚手架项目中,关于PDF的依赖老生常用的就那么几个。**pdfmake,vue-print-nb,v-html5-renderer,print-js,html2pdf.js,vue-pdf。**总结起来无非就是达到将内容生成pdf,预览pdf这两个业务场景。

本篇讲的是通过html2canvas+jspdf来动态指定div内容转化为pdf

html2canvas 可以将 HTML 画布(canvas)捕捉为图像,然后 jspdf 可以将这些图像转换为 PDF 格式

第一步先安装依赖

bash 复制代码
npm install jspdf html2canvas --save
# 或者
yarn add jspdf html2canvas

2.效果展示及源码

导出后一个div为一个pdf页面,不足的留空白。超出的会自动加页面补充。假设,你首页想指定一个图片作为封面,中间的一大段内容从第二页开始,自动往后分页。那就设置两个div就行了。

PDF生成后的大致效果

下面附上代码,就一个vue文件,方便各位拿来即用,能立马看到效果:

html 复制代码
<template>
    <div id="pdfinsurancepdf">
        <div style="width: 490pt;margin: auto;">
            <div class="title" style="padding:20pt">
                <el-button type="primary" @click="downpdf">下载PDF</el-button>
                 <el-divider></el-divider>
            </div>
            <div id="page1">
                <img src="@/assets/1.jpg" style="width:100%;height:auto" alt="封面" />
            </div>
            <div id="page2">
                    <template>
                    <el-table
                    :data="tableData"
                    style="width: 100%">
                    <el-table-column
                        prop="date"
                        label="日期"
                        width="180">
                    </el-table-column>
                    <el-table-column
                        prop="name"
                        label="姓名"
                        width="180">
                    </el-table-column>
                    <el-table-column
                        prop="address"
                        label="地址">
                    </el-table-column>
                    </el-table>
                </template>
                <div>
                    <pre>
当你在凝视着网页的时候
网页也正在凝视着你
流情|导航站
Who is liuqing?

种一棵树最好的时间是十年前,然后就是现在------致想做还未来得及做的你

How lucky to meet you!

你好,这里是流情 Liuqing ,26岁,技术宅,对有趣的世界和可能有趣的你感到好奇,热爱IT和国风文化,
从事互联网产品/Web开发相关工作。希望能与你在比特之海的繁星之下相见!
                    </pre>
                </div>  
            </div>
            <div id="page3">
                <div>
                    <img src="@/assets/2.jpg" style="width:100%;height:auto" alt="结束页" />
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import html2canvas from 'html2canvas';
import JsPDF from 'jspdf';
export default {
    name:'insurancepdf',
    data() {
        return {
            compony:"pdf导出多页测试",
            tableData: [{
                date: '2016-05-02',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1518 弄'
            }, {
                date: '2016-05-04',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1517 弄'
            }, {
                date: '2016-05-01',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1519 弄'
            }, {
                date: '2016-05-03',
                name: '王小虎',
                address: '上海市普陀区金沙江路 1516 弄'
            }]
            }
    },
    moutned() {
        console.log(123)
    },
    methods:{
        downpdf(){
            const pdf = new JsPDF('p', 'mm', 'a4');
            var divIds = ['page1', 'page2','page3'];
            const promises = divIds.map(divId => {
                const div = document.getElementById(divId);
                return html2canvas(div, {
                    allowTaint: false,
                    taintTest: false,
                    logging: false,
                    useCORS: true,
                    dpi: window.devicePixelRatio * 1,
                    scale: 2        //画布分辨率
                });
            });
            
            Promise.all(promises).then(canvases => {
                canvases.forEach((canvas, index) => {
                    if (index > 0) {
                        pdf.addPage();
                    }
                    this.addCanvasToPdf(pdf, canvas);
                });
                pdf.save('pdf导出多页测试.pdf');
            }).catch(error => {
                console.error('Error generating PDF:', error);
            });
        },
        addCanvasToPdf(pdf,canvas){
            // 接下来使用canvas创建PDF
            var ctx = canvas.getContext('2d');
            var a4w = 190; var a4h = 277; // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
            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;
            }
        }
    }
    
}
</script>
<style scoped>
    #pdfinsurancepdf{
        width: 100%;
        background: #fff;
    }
    span{
        line-height: 30pt;
    }
</style>
相关推荐
耘田5 分钟前
Markdown to PDF/PNG Converter
pdf
AirDroid_cn1 天前
PDF转图片需要用到什么技术?苹果手机怎样将PDF转为jpg?
pdf·iphone·ipad·快捷指令
拓端研究室1 天前
专题:2025全球消费趋势与中国市场洞察报告|附300+份报告PDF、原数据表汇总下载
大数据·信息可视化·pdf
Kyln.Wu3 天前
【python实用小脚本-190】Python一键删除PDF任意页:输入页码秒出干净文件——再也不用在线裁剪排队
服务器·python·pdf
阿幸软件杂货间3 天前
免费万能电子书格式转换器!Neat Converter支持 ePub、Azw3、Mobi、Doc、PDF、TXT 文件的相互转换。
pdf·格式转换
星马梦缘4 天前
CSDN转PDF【无水印且免费!!!】
pdf·免费·pandoc·转pdf·无水印·csdn转pdf·wkhtmlpdf
画月的亮4 天前
前端处理导出PDF。Vue导出pdf
前端·vue.js·pdf
伊织code4 天前
pdfminer.six
python·pdf·图片·提取·文本·pdfminer·pdfminer.six
HAPPY酷5 天前
给纯小白的Python操作 PDF 笔记
开发语言·python·pdf
代码AI弗森6 天前
PDF OCR + 大模型:让文档理解不止停留在识字
pdf·ocr