解决vue项目中html2canvas+jspdf 当前页面生成pdf 模糊,分辨率低的问题

上一篇文章总结了怎么把当前页面,生成PDF,测试的时候发现不同的电脑,下载下来的文件大小不一样,清晰度也不一样。不知是否和电脑屏幕的分辨率有关,这个存疑。

百度了一整天,终于找到了解决方案,勉强解决了清晰度问题,不知后面还会出现什么bug。

生成pdf的参考原文: https://blog.csdn.net/pratise/article/details/79249943

解决清晰度问题的参考原文: https://blog.csdn.net/weixin_44309374/article/details/106924138

接下来记录一下我解决清晰度问题后的代码,做个留存:

我需要导出的是单页的,高度不超出a4高度的一个表格,所以不考虑分页问题

如果需要导出的是简单的表格之类的,快速获取这个表格的html代码,可以在csdn的创作中心,将word中的表格复制过来,发布博客后,查看源码,就能获得这个表格的html代码(我是这么做的,如果有其他的方法请告诉我哈哈)

(1)我按第二篇参考中的 第二种方法,将  html2canvas.js(点此处跳转)文件  下载到本地    。其实下载了这个文件  ,之前npm insatll 的html2canvas 就用不到的。这里可以随你心情要不要npm uninstall html2canvas。

(2)新建 htmlToPdf.js    代码中的注释,写了一些我自己的理解

// 导出页面为PDF格式
import './html2canvas'
//引入的路径请根据自己的实际情况来写
import JsPDF from 'jspdf'
export default{
 install (Vue, options) {
  Vue.prototype.getPdf = function (dom,title) {
   var title = title
   
   html2canvas(document.querySelector(dom), {
    // 以下字段可选
    width: 592.28, // canvas宽度
    height: 650, // canvas高度   这个高度高于div元素的话,底部会出现黑块 ,相当于leftHeight
    //  (宽度固定情况下) 小于下面的841.89就不会分页
    x: 0, // x坐标
    y: 0, // y坐标
    foreignObjectRendering: true, // 是否在浏览器支持的情况下使用ForeignObject渲染
    useCORS: true, // 是否尝试使用CORS从服务器加载图像
    async: false, // 是否异步解析和呈现元素

    // 以下字段必填
    background: "#ffffff", // 一定要添加背景颜色,否则出来的图片,背景全部都是透明的
    dpi: 450, // 处理模糊问题,越高越清晰,文件越大
    onrendered: function (canvas) {
     
        let url = canvas.toDataURL();
        let contentWidth = canvas.width
        let contentHeight = canvas.height
        console.log("画布宽度:",canvas.width)
        console.log("画布高度:",canvas.height)

        //  a4 的宽高    592.28 * 841.89
        let pageHeight = contentWidth / 592.28 * 841.89 //width是592.28,height <841.89就不会分页
        let leftHeight = contentHeight  //height     小于 width / 592.28    * 841.89 就不会分页
        let position = 0
        let imgWidth = 595.28
        let imgHeight = 592.28 / contentWidth * contentHeight
        let pageData = canvas.toDataURL('image/jpeg', 1.0)
        let PDF = new JsPDF('', 'pt', 'a4')
        console.log("left:",leftHeight,"pageHeight:",pageHeight)

        //强制不分页
        // PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        
        if (leftHeight < pageHeight) {
         PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
        } else { //leftHeight>pageHeight
        
         while (leftHeight > 0) {
          PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
          leftHeight -= pageHeight     
          position -= 841.89   
          if (leftHeight > 0) {
           PDF.addPage()
          }
         }

        }

        PDF.save(title + '.pdf')
    },
});

  }
 }
}

(3) main.js中全局注册

import htmlToPdf from '@/components/utils/htmlToPdf'
// 引入的路径请根据自己的实际情况来写

Vue.use(htmlToPdf)

(4)要导出的当前页面:html.vue

<template>
    <!-- <div id="pdfDom" style="text-align: center;width:595.28px;height:841.89px;color:black;background-color:white"> -->
    <div id="pdfDom" style="text-align: center;width:595.28px;height:650px;color:black;background-color:white">

    <h3 style="padding-top:30px;padding-bottom:10px;">标题</h3>
        <div style="text-align:right">
      <span style="text-align:right;margin:50px;padding-bottom:15px;">打印日期:{{date}}</span>
    </div>
    <table style="width:387pt;margin:auto;border-color:black; " cellspacing="0" border="1">
      <tbody class="body">
        <tr>
          <td colspan="2" class="td1">申请人组织机构代码</td>
          <td colspan="2" class="td2">{{obj.certNo}}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">申请人名称</td>
          <td colspan="2" class="td2">{{obj.custName}}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">啊啊啊啊</td>
          <td colspan="2" class="td2">{{obj.paymentNo}}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">业务品种</td>
          <td colspan="2" class="td2">非融资性保函</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">T24借据编号</td>
          <td colspan="2" class="td2">{{obj.coreSeriNo}}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">签发币种</td>
          <td colspan="2" class="td2">人民币</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">签发金额(元)</td>
          <td colspan="2" class="td2">{{ obj.parAmt }}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">签发日</td>
          <td colspan="2" class="td2">{{obj.tkEffDt }}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">到期日</td>
          <td colspan="2" class="td2">{{obj.exprtnDt }}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">保函类型</td>
          <td colspan="2" class="td2">
           啊啊啊啊
          </td>
        </tr>
        <tr>
          <td colspan="2" class="td1">保函受益人</td>
          <td colspan="2" class="td2">{{obj.tendereeName}}</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">系统审批结果</td>
          <td colspan="2" class="td2">通过</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">保证金是否入账</td>
          <td colspan="2" class="td2">是</td>
        </tr>
        <tr>
          <td colspan="2" class="td1">手续费是否收妥</td>
          <td colspan="2" class="td2">是</td>
        </tr>
        <tr>
          <td  class="right_bottom" style="width:80pt;text-align: left;border-width:0px 1px 1px 0px;">登记人员</td>
          <td  class="right_bottom" style="width:127.75pt;text-align: left;border-width:0px 1px 1px 0px;">{{obj.userName||obj.cstMrgNo}}</td>
          <td  class="right_bottom" style="width:79.05pt;text-align: left;border-width:0px 1px 1px 0px;">登记机构</td>
          <td  style="width:150.2pt;text-align: left;border-width:0px 0px 1px 0px;border-bottom: solid 1px #000;">{{obj.orgName||obj.orgId}}</td>
        </tr>
        <tr>
          <td style="width:80pt;text-align: left;border-width:0px 1px 0px 0px;border-right: solid 1px #000;">登记时间</td>
          <td style="width:127.75pt;text-align: left;border-width:0px 1px 0px 0px;border-right: solid 1px #000;">{{obj.tkEffDt}}</td>
          <td style="width:79.05pt;text-align: left;border-width:0px 1px 0px 0px;border-right: solid 1px #000;">业务归属机构</td>
          <td style="width:150.2pt;text-align: left;border-width:0px 0px 0px 0px;">{{obj.signOrgName||obj.signOrgId}}</td>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
const moment = require('moment');

export default {
  data() {
    return {
      date: moment(new Date()).format("YYYY-MM-DD"),
    }
  },
  props: {
    obj: {
      type: Object,
      default() {
        return {

        };
      }
    },

  },
  methods: {
    get() {
      this.getPdf('#pdfDom', "文件名");
    },

  }
}
</script>

<style lang="less" scoped>
.body td {
  padding: 5px 0px 5px 5px;
}

.td1 {
  width: 207.75pt;
  text-align: left;
  border-width: 0px 1px 1px 0px;
  border-right: solid 1px #000;
  border-bottom: solid 1px #000;
}


.right_bottom{
   border-right: solid 1px #000;
  border-bottom: solid 1px #000;
  
}

.td2 {
  width: 207.75pt;
  text-align: left;
  border-width: 0px 0px 1px 0px;
  border-bottom: solid 1px #000;
}
</style>

(4) 调用html.vue的页面   

注意: 如果导出页面的顶部不在窗口内,比如说超出了屏幕高度,而往下滑,导致看不到顶部,那生成的pdf会截取能看到的那部分,并且底部会有黑块。所以我把下载按钮放在<html>上面,确保要

打印的页面是能看到头部的。

<template>
  <div>
    <Button @click="show">下载</Button>
    <html ref="gethtml" :obj="obj"></html>
  </div>
</template>


<script>
import toHtml from "./component/html"
export default {
  data() {
    return {
      load: false,
      obj: {
        
      }

    };
  },
  components: { html },
  methods: {
    show() {
      console.log("点了")

      this.$refs.gethtml.get();


    }
  }
};
</script>

大概就是这样,由于不能把我实际的代码贴出来,直接复制的话可能不能使用,有问题请在评论找我。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值