程序员的资源宝库

网站首页 > gitee 正文

html页面转PDF、图片操作记录

sanyeah 2024-04-25 18:46:45 gitee 11 ℃ 0 评论

  前言

  日常开发中,我们有可能会碰到从系统中导出数据并打印的需要,打印的格式是常规的表格形式,例如:

 

  本文记录使用js库html2canvas + jspdf实现html转PDF、图片,并下载

 

  画出页面

  对于我们后端开发人员来说,画这样的表格页面还是比较耗时的,我们可以另辟蹊径,在word文档画好表格,并设置好数据,再另存为html页面,这样就得到我们想要的表格页面

  新建一个Word文档,画出我们想要的表格格式,其中姓名等信息是程序输入,备注、签名等是打印出来后手写

 

   再另存为HTML文件,查看这个HTML文件的源代码,注意要复制的代码

 

 

   把代码复制到我们的项目中即可

 

  项目应用

  我们是一个vue项目,如何搭建vue项目可以看回我们之前的博客:Vue项目入门实例

  首先有个common工具类,封装引入在线js的方法

/**
 * common工具类
 */
export default {
    //根据url引入js
    importJsByUrl(url){
        const element = document.createElement("script");
        element.src = url;
        document.body.appendChild(element);
    },
}

 

  简单的页面

 <template>
    <div>
        <el-row style="text-align: center;">
            <el-button v-on:click="pdf">转PDF</el-button>
            <el-button v-on:click="img">转图片</el-button>
        </el-row>
        <div style="display: flex;justify-content: center;">
            <div class="app-ccontent">
                 <!-- 我们复制出来的html代码就放在这里 -->
             </div>
        </div>
    </div>
</template>

<script>
    import CommonUtil from "@/utils/commonUtil.js"

    export default {
        data(){
          return{
              user:{//模拟数据
                  name:"huanzi-qch",
                  age:"2020年11月",
                  nativePlace:"广西南宁",
                  nowLiving:"广东广州"
              }
          }
        },
        created() {
            //引入 html2canvas、jspdf
            CommonUtil.importJsByUrl("https://cdn.bootcss.com/html2canvas/0.5.0-alpha2/html2canvas.min.js");
            CommonUtil.importJsByUrl("https://cdn.bootcss.com/jspdf/1.5.3/jspdf.min.js");
        },
        methods:{
            //转成PDF并下载
            pdf(){
  
            },
            //转成图片并下载
            img(){

            },
        }
    }
</script>

<style scoped>
    .app-ccontent{
        padding: 20px;
        width: 794px;
        background-color: #eef1f5;
    }
</style>

  完整代码,复制过来的html代码,最外层的div新增id属性:id="body" ,方便html2canvas获取元素内容转成canvas画布

<template>
    <div>
        <el-row style="text-align: center;">
            <el-button v-on:click="pdf">转PDF</el-button>
            <el-button v-on:click="img">转图片</el-button>
        </el-row>
        <div style="display: flex;justify-content: center;">
            <div class="app-ccontent">
            <div class="Section0" id="body" style="layout-grid:15.6000pt;" >
                <h2 align=center  style="text-align:center;" ><b><span style="mso-spacerun:'yes';font-family:黑体;mso-ascii-font-family:Arial;
mso-hansi-font-family:Arial;mso-bidi-font-family:'Times New Roman';font-weight:bold;
font-size:16.0000pt;mso-font-kerning:1.0000pt;" ><font face="黑体" >导出</font></span></b><b><span style="mso-spacerun:'yes';font-family:黑体;mso-ascii-font-family:Arial;
mso-hansi-font-family:Arial;mso-bidi-font-family:'Times New Roman';font-weight:bold;
font-size:16.0000pt;mso-font-kerning:1.0000pt;" >PDF/<font face="黑体" >图片测试</font></span></b><b><span style="mso-spacerun:'yes';font-family:Arial;mso-fareast-font-family:黑体;
mso-bidi-font-family:'Times New Roman';font-weight:bold;font-size:16.0000pt;
mso-font-kerning:1.0000pt;" ><o:p></o:p></span></b></h2><table class=MsoTableGrid  border=1  cellspacing=0  style="border-collapse:collapse;width:99.9600%;border:none;
mso-border-left-alt:0.5000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;mso-border-insideh:0.5000pt solid windowtext;mso-border-insidev:0.5000pt solid windowtext;
mso-padding-alt:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;" ><tr style="height:23.3500pt;" ><td width=24.9800%  valign=top  style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;
mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >姓名</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=24.9800%  valign=top  style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >{{user.name}}</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000%  valign=top  style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >出生年月</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000%  valign=top  style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >{{user.age}}</span><span style="font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';
font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td></tr><tr style="height:24.1000pt;" ><td width=24.9800%  valign=top  style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;
mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >籍贯</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=24.9800%  valign=top  style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >{{user.nativePlace}}</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000%  valign=top  style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >现居住</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=25.0000%  valign=top  style="width:25.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;line-height:200%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >{{user.nowLiving}}</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td></tr><tr style="height:30.2000pt;" ><td width=24.9800%  valign=top  style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;
mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-autospace:ideograph-numeric;mso-pagination:none;text-align:center;
line-height:700%;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;
mso-font-kerning:1.0000pt;" >备注</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=75.0000%  valign=top  colspan=3  style="width:75.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  style="line-height:200%;" ><span style="font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';
font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal  style="line-height:200%;" ><span style="font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';
font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal  style="line-height:200%;" ><span style="font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';
font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p>&nbsp;</o:p></span></p></td></tr><tr style="height:72.7000pt;" ><td width=24.9800%  valign=center  style="width:24.9800%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;
mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  align=center  style="text-align:center;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';line-height:200%;
font-size:12.0000pt;mso-font-kerning:1.0000pt;" >本人确认</span><span style="font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';
font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p></o:p></span></p></td><td width=75.0000%  valign=center  colspan=3  style="width:75.0000%;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:none;
mso-border-left-alt:none;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;
border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;
mso-border-bottom-alt:0.5000pt solid windowtext;" ><p class=MsoNormal  style="text-indent:12.0000pt;mso-char-indent-count:1.0000;" ><span style="font-family:宋体;mso-ascii-font-family:仿宋_GB2312;line-height:200%;
font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal  style="text-indent:12.0000pt;mso-char-indent-count:1.0000;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >本人已知悉。</span><span style="font-family:仿宋_GB2312;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;
mso-bidi-font-family:宋体;line-height:200%;font-size:12.0000pt;
mso-font-kerning:0.0000pt;" ><o:p></o:p></span></p><p class=MsoNormal  style="text-indent:12.0000pt;mso-char-indent-count:1.0000;" ><span style="font-family:仿宋_GB2312;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;
mso-bidi-font-family:宋体;line-height:200%;font-size:12.0000pt;
mso-font-kerning:0.0000pt;" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal style="text-indent: 192pt;"><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >本人</span><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >签名:</span><span style="font-family:宋体;mso-ascii-font-family:仿宋_GB2312;line-height:200%;
font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p></o:p></span></p><p class=MsoNormal ><span style="font-family:仿宋_GB2312;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;
mso-bidi-font-family:宋体;line-height:200%;font-size:12.0000pt;
mso-font-kerning:0.0000pt;" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal  style="text-indent:270.0000pt;mso-char-indent-count:16.0000;" ><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;margin-right: 30px;" ></span><span style="font-family:宋体;mso-ascii-font-family:仿宋_GB2312;line-height:200%;
font-size:12.0000pt;mso-font-kerning:0.0000pt;" >&nbsp;</span><span style="font-family:宋体;mso-ascii-font-family:仿宋_GB2312;line-height:200%;
font-size:12.0000pt;mso-font-kerning:0.0000pt;" >&nbsp;</span><span style="font-family:宋体;mso-ascii-font-family:仿宋_GB2312;line-height:200%;
font-size:12.0000pt;mso-font-kerning:0.0000pt;" >&nbsp;</span><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;margin-right: 30px;" ></span><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" >&nbsp;&nbsp;</span><span style="mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:仿宋_GB2312;
line-height:200%;font-size:12.0000pt;mso-font-kerning:0.0000pt;" ></span><span style="font-family:宋体;mso-ascii-font-family:仿宋_GB2312;line-height:200%;
font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p></o:p></span></p><p class=MsoNormal  style="text-indent:192.0000pt;mso-char-indent-count:16.0000;" ><span style="font-family:宋体;mso-ascii-font-family:仿宋_GB2312;line-height:200%;
font-size:12.0000pt;mso-font-kerning:0.0000pt;" ><o:p>&nbsp;</o:p></span></p></td></tr></table><p class=MsoNormal ><span style="mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋体;
mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;" ><o:p>&nbsp;</o:p></span></p></div>
            </div>
        </div>
    </div>
</template>

<script>
    import CommonUtil from "@/utils/commonUtil.js"

    export default {
        data(){
          return{
              user:{
                  name:"huanzi-qch",
                  age:"2020年11月",
                  nativePlace:"广西南宁",
                  nowLiving:"广东广州"
              }
          }
        },
        created() {
            //引入 html2canvas、jspdf
            CommonUtil.importJsByUrl("https://cdn.bootcss.com/html2canvas/0.5.0-alpha2/html2canvas.min.js");
            CommonUtil.importJsByUrl("https://cdn.bootcss.com/jspdf/1.5.3/jspdf.min.js");
        },
        methods:{
            pdf(){
                window.html2canvas(document.getElementById("body"), {
                    allowTaint: true,
                    useCORS: true,
                    scale: 2,
                    background: "#eef1f5",
                }).then(function(canvas) {
                    let contentWidth = canvas.width;
                    let contentHeight = canvas.height;
                    //一页pdf显示html页面生成的canvas高度;
                    let pageHeight = contentWidth / 592.28 * 841.89;
                    //未生成pdf的html页面高度
                    let leftHeight = contentHeight;
                    //页面偏移
                    let position = 0;
                    //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
                    let imgWidth = 595.28;
                    let imgHeight = 592.28/contentWidth * contentHeight;

                    let pageData = canvas.toDataURL('image/jpeg', 1.0);

                    let pdf = new window.jsPDF('', 'pt', 'a4');

                    //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
                    //当内容未超过pdf一页显示的范围,无需分页
                    if (leftHeight < pageHeight) {
                        pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
                    } else { // 分页
                        while(leftHeight > 0) {
                            pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
                            leftHeight -= pageHeight;
                            position -= 841.89;
                            //避免添加空白页
                            if(leftHeight > 0) {
                                pdf.addPage();
                            }
                        }
                    }
                    pdf.save('exportPdf.pdf');
                })
            },
            img(){
                window.html2canvas(document.getElementById("body"), {
                    allowTaint: true,
                    useCORS: true,
                    scale: 2,
                    background: "#eef1f5",
                }).then((canvas) => {
                    //创建一个隐藏的下载a标签
                    let link = document.createElement("a");
                    link.style.display = "none";
                    link.setAttribute("download", "exportImg.png");
                    link.href = canvas.toDataURL('image/png');

                    document.body.appendChild(link);
                    link.click();  // 执行 <a> 元素的下载

                    //过河拆桥
                    link.remove();
                });
            },
        }
    }
</script>

<style scoped>
    .app-ccontent{
        padding: 20px;
        width: 794px;
        background-color: #eef1f5;
    }
</style>
View Code

 

  关键代码

//转成PDF并下载
pdf(){
    window.html2canvas(document.getElementById("body"), {
        allowTaint: true,
        useCORS: true,
        scale: 2,
        background: "#eef1f5",
    }).then(function(canvas) {
        let contentWidth = canvas.width;
        let contentHeight = canvas.height;
        //一页pdf显示html页面生成的canvas高度;
        let pageHeight = contentWidth / 595.28 * 841.89;
        //未生成pdf的html页面高度
        let leftHeight = contentHeight;
        //页面偏移
        let position = 0;
        //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
        let imgWidth = 595.28;
        let imgHeight = 595.28/contentWidth * contentHeight;

        let pageData = canvas.toDataURL('image/jpeg', 1.0);

        let pdf = new window.jsPDF('', 'pt', 'a4');

        //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
        //当内容未超过pdf一页显示的范围,无需分页
        if (leftHeight < pageHeight) {
            pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
        } else { // 分页
            while(leftHeight > 0) {
                pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
                leftHeight -= pageHeight;
                position -= 841.89;
                //避免添加空白页
                if(leftHeight > 0) {
                    pdf.addPage();
                }
            }
        }
        pdf.save('exportPdf.pdf');
    })
},
//转成图片并下载
img(){
    window.html2canvas(document.getElementById("body"), {
        allowTaint: true,
        useCORS: true,
        scale: 2,
        background: "#eef1f5",
    }).then((canvas) => {
        //创建一个隐藏的下载a标签
        let link = document.createElement("a");
        link.style.display = "none";
        link.setAttribute("download", "exportImg.png");
        link.href = canvas.toDataURL('image/png');

        document.body.appendChild(link);
        link.click();  // 执行 <a> 元素的下载

        //过河拆桥
        link.remove();
    });
},

 

  效果

  页面

 

 

  下载下来的文件

 

 

 

  2021-03-04更新:

  问题:当PDF需要分页时,存在文字被分割的现象

  解决:我们首先获取html转成PDF后,对应的一页的高度,然后获取所有最小的不可被分割的对象(此处为p标签),遍历进行高度判断,当刚好在要被分割,则加一个margin-top把页面撑开

    //处理PDF分页
    var disposeDomList = [];
    function disposeHtml(){
        //一页pdf显示html页面生成的canvas高度 a4纸的尺寸[595.28,841.89]
        let pageHeight = document.getElementById("body").clientWidth / 595.28 * 841.89;
        
        let elementsByTagName = document.getElementsByTagName("p");
        for (let i = 0; i < elementsByTagName.length; i++) {
            let dom = elementsByTagName[i];
            let boxHeight = 20;
            //这里计算高度时,要加上预留的上下边距(大概20)
            if (dom.offsetTop % pageHeight + (dom.offsetHeight + boxHeight) >= pageHeight) {
                let newMarginTop = (dom.offsetHeight + boxHeight * 3) + "px";

                console.log(dom);
                disposeDomList.push({
                    dom:dom,
                    oldMarginTop:dom.style.marginTop
                });

                dom.style.marginTop = newMarginTop;
            }
        }
    }

  使用:

    //转成PDF并下载
    function pdf(){
        //处理dom
        disposeHtml();

        //省略其他代码...
        
        //html恢复原样
        disposeDomList.forEach(function (value) {
            value.dom.style.marginTop = value.oldMarginTop;
        })
    }

 

 

  处理前:

 

 

 

 

 

  处理中:

  找到两个地方,并设置margin-top

 

 

   处理后:

 

 

 

 

 

  后记

  转成PDF后就可以方便的进行打印了;转成图片后就方便把文件发给领导看了;nice!

 

  参考文章:

  https://segmentfault.com/a/1190000009211079

  https://segmentfault.com/a/1190000015820189

  https://www.cnblogs.com/xinjie-just/p/13513118.html

  https://juejin.cn/entry/6844903586682372109

  https://blog.csdn.net/cpongo3/article/details/93623678

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表