【html转pdf】html页面导出为pdf文件,纯html版本,简单实现pdf转换【html2canvas+jspdf】

前言

最近遇到的需求,把html转成pdf文件下载导出。
目前网上看了下,有三种方法,但是其中两种需要后端配合
一种是纯前端实现的,比较简单。所以就使用了这种。
也就是html2canvas + jspdf 的这种方法
这种方法实现的思路就是,通过html2canvas 把元素内的数据截图出来成一个图片
然后把这个图片通过jspdf 方法转成pdf格式输出出来
但是也有缺点,就是只是一个图片,而且清晰度也没有那么高。
只能说勉强实现一个需求,先应付一下,后续会继续看其他的写法,然后更新

效果图

这里是导出来后的效果,pdf格式的。只有一页
【html转pdf】html页面导出为pdf文件,纯html版本,简单实现pdf转换【html2canvas+jspdf】_第1张图片
这里是网页上的,这个报告都是我排班出来的,图片和数据都是网上随便复制的,点击导出后会生成一个pdf文件。右边一大串的是base64格式的图片地址。也就是截图。
【html转pdf】html页面导出为pdf文件,纯html版本,简单实现pdf转换【html2canvas+jspdf】_第2张图片

代码

这是html版本的,然后引入了vue的框架。
这里核心的是要引入html2canvas.js和jspdf.debug.js
资源的话我上传了,可以点击我的资源去下载,我设置了0积分下载,应该是可以直接下载
如果你们用的是纯vue版本,那就简单了。直接npm 下载这两个插件就行。

第一个.将页面html转换成图片 npm install --save html2canvas
第二个.将图片生成pdf npm install jspdf --save

<!DOCTYPE html>
<html>

<head>
  <meta charset='UTF-8'>
  <!-- 先引入 Vue -->
  <script src='vue.js'></script>
  <!-- 引入element-UI组件 -->
  <script src='element.js'></script>
  <link rel='stylesheet' href='element-index.css'>
  <!-- 引入axios -->
  <script src='axios.min.js'></script>

  <!-- 引入html2canvas 和 jspdf.debug-->
  <script src='./node_modules/html2pdf/js/html2canvas.js'></script>
  <script src='./node_modules/html2pdf/js/jspdf.debug.js'></script>
  
</head>

<body>
  <div id="app">
    <div class="layout">
      <div><button @click="downBtn" style="width: 70px; height: 30px" id="download-paper">pdf导出</button></div>
      <div ref="html2canvas" id="html2canvas">
        <div class="title">
          <div class="title_img">
            <img src="https://img2.baidu.com/it/u=384718229,1745978279&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=461" alt="" style="width: 70px;"  crossorigin="anonymous">
          </div>
          <div class="title_text">
            <p class="yiyuan">第一人民医院</p>
            <p style="font-size: 18px;font-weight:bold">消化内镜检查及手术记录报告</p>
          </div>
        </div>
        <div class="info1">
          <div class="info1left">检查号:12-10266</div>
          <div class="info1right">仪器型号:12-10266</div>
        </div>
        <div class="info2">
          <div class="info2top">
            <div>姓名:王小天</div>
            <div>性别:男</div>
            <div>年龄:34</div>
            <div>科别:内科</div>
            <div>申请医师:黄小燕</div>
          </div>
          <div class="info2bottom">
            <div>病历号:12312313546546464</div>
            <div>住院号:y229397</div>
            <div>病区号:四病区</div>
            <div>床位号:409</div>
          </div>
        </div>
        <div class="info3">
          <div>检查图像:</div>
          <div>
            <img :src="item" alt="" class="changimg" v-for="item,index in img2" :key="index"  crossorigin="anonymous">
          </div>
        </div>
        <div class="info4">
          <div style="font-weight: bold;margin-bottom: 5px;">内镜所见</div>
          <div style="font-size:14px;">食管:黏膜光滑柔软,血管纹理清晰,扩张度好,齿状线清晰。贲门:粘膜光滑,未见异常。 胃底:见一枚0.4*0. 4cm大小息肉,表面充血,予以摘除送检,粘液湖黄色,大量。胃
            体:粘膜色泽潮红,下部窦体交界后壁见粘膜凹陷不平,片状发红,子以活检。胃角:后壁见片状发红糜烂灶,予以活检。胃窦: 胃窦后壁见大片状食管:黏膜光滑柔软,血管纹理清晰,扩张度好,齿状线清晰。贲
            门:粘膜光滑,未见异常。 胃底:见一枚0.4*0. 4cm大小息肉,表
            面充血,予以摘除送检,粘液湖黄色,大量。胃 体:粘膜色泽潮
            红,下部窦体交界后壁见粘膜凹陷不平,片状发红,子以活检。胃
            角:后壁见片状发红糜烂灶,予以活检。胃窦: 胃窦后壁见大片状
            发红病灶,表面不平,部分隆起、部分凹陷,染色表面结构紊乱,予以
            活检。幽门: 呈圆形,开闭尚可,粘膜色泽淡红,未见出血及渍
            疡。十二指肠: 球部及降部未见异常。活检。幽门: 呈圆形,开闭尚可,粘膜色泽淡红,未见出血及渍疡。十二指肠: 球部及降部未见异常。
          </div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">镜下诊断</div>
          <div style="font-size:14px;">
            1,胃多发病灶性质待定
            2,胃底息肉镜下摘除
            3,胆汁反流性胃炎
          </div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">病理号:</div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">活检部位:胃底、窦体交界后壁、胃窦后壁、</div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">病理诊断:</div>
          <div style="font-weight: bold;margin-bottom: 5px;margin-top: 10px;">医生建议:</div>
        </div>
        <div class="info5">
          <div>南京索图科技有限公司</div>
          <div>手术及诊断医师:王晓</div>
          <div>助手:</div>
          <div>检查日期:2022/8/27</div>
        </div>
        <div style="text-align:center;font-weight: bold;font-size: 14px;">仅供临床参考,不做证明材料!</div>
      </div>

    </div>
  </div>
</body>
<script>
  new Vue({
    el: '#app',
    data() {
      return {
        img2: [
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
          'https://pics6.baidu.com/feed/562c11dfa9ec8a13d9cd9e4f08e1e488a2ecc0b1.jpeg?token=687c57c1c319d6c576d27df01e88c2cb',
        ]
      };
    },
    mounted() {

    },
    methods: {
      downBtn() {
        let dom = document.getElementById("html2canvas");
        //调用方法下载
        html2canvas(dom, {
          useCORS: true, //允许跨域
          allowTaint: false,
          logging: false,
          letterRendering: true,
          ddpi: window.devicePixelRatio * 4, //将分辨率提高到特定的DPI 提高四倍
          scale: 4, //按比例增加分辨率
          background: '#fff'//pdf背景色为白色,默认是黑色的
        }).then((canvas) => {
          //返回图片dataURL,参数:图片格式和清晰度(0-1)
          var pageData = canvas.toDataURL('image/jpeg', 1.0);

          //方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
          var pdf = new jsPDF('', 'pt', 'a4');

          //addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
          pdf.addImage(pageData, 'JPEG', 0, 0, 595.28, 592.28 / canvas.width * canvas.height);

          //保存到pdf,名字是stone
          pdf.save('stone.pdf');

        });
      },

    },
  })
</script>
<style>
  #html2canvas {
    width: 800px;
    height: 1280px;
    padding: 20px;
  }

  .title {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100px;
  }
  .title_text {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .yiyuan {
    font-size: 20px;
    font-weight: bold;
    color: blue;
  }

  .info1 {
    height: 30px;
    display: flex;
    justify-content: space-between;
    border-bottom: 1px solid #222;
  }

  .info2 {
    height: 100px;
    border-bottom: 1px solid #222;
  }

  .info3 {
    border-bottom: 1px solid #222;
  }
  .info4{
    border-bottom: 1px solid #222;
  }
  .info5{
    display: flex;
    justify-content: space-around;
    align-items: center;
    height: 50px;
  }
  .info2top {
    display: flex;
    justify-content: space-around;
    align-items: center;
    height: 40px;
  }

  .info2bottom {
    display: flex;
    justify-content: space-around;
    align-items: center;
    height: 40px;
  }

  .changimg {
    width: 180px;
    margin-right: 15px;
  }
</style>

</html>

细节事项

1,模糊问题通过html2canvas方法内的ddpi和scale放大控制清晰度
2,你下载的时候,导出按钮要放在上面,不能放在最下面,因为可能会由于你页面长了有滚动条,当你滚动到下面点击按钮的时候,上面滚动条看不到的部分是不会被截图的,也就是截图不全。但是如果你把按钮放在顶部,那就可以截全,哪怕下面的滚动部分看不到也可以截全,不知道是为啥。反正这个坑我是踩了,提醒你们一下。
3,这里是简单版本,所以没有分页功能,如果需要分页功能可以去网上找一下,pdf.addPage();这个方法就是添加新的分页,可以通过判断是否后面还有内容来触发这个方法,网上到处都是可以直接复制使用
这里给你们随便复制一个人的代码做参考

getPdf(title,url) {
        html2Canvas(document.querySelector('#pdfDom'), {
            allowTaint: false,
            taintTest: false,
            logging: false,
            useCORS: true,
            dpi: window.devicePixelRatio*4, //将分辨率提高到特定的DPI 提高四倍
            scale:4 //按比例增加分辨率
        }).then(canvas=>{
            var pdf = new jsPDF('p', 'mm', 'a4');    //A4纸,纵向
            var ctx = canvas.getContext('2d'),
                a4w = 190, a4h = 277,    //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
                imgHeight = Math.floor(a4h * canvas.width / a4w),    //按A4显示比例换算一页图像的像素高度
                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')
        })
    }

————————————————
版权声明:本文为CSDN博主「inticaler」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/MICHAEL_PRINCE/article/details/118667848

4,注意这里页面的图片都是需要添加 crossorigin=“anonymous” 这句话的,这句话的意思是图片允许跨域,不然会出现图片空白的情况。
5,图片的地址如果你要测试,他只能接受http的那种或者base64格式的。不可以本地引入,像 . /xxx/xxx/xxx.png这种的路径是会报错的,我这里用的测试图片都是网络上的地址。

2023/5/22更新,如果需要导出图片格式,用这个方法就行了。其他啥也不用动

clickGeneratePicture() {
                let ref = this.$refs.html2canvas; // 截图区域
                html2canvas(ref, {
                        backgroundColor: "#142E48"
                    })
                    .then(canvas => {
                        let dataURL = canvas.toDataURL("image/png");
                        this.dataURL = dataURL;
                        let creatDom = document.createElement("a");
                        document.body.appendChild(creatDom);
                        creatDom.href = dataURL;
                        creatDom.download = "导出的图片名";
                        creatDom.click();
                    })
                    .catch(err => {
                        this.$message({
                            message: "图片生成失败",
                            type: "error"
                        });
                    });
            }

你可能感兴趣的:(功能实现,html,前端,html转pdf,html2canvas,jspdf)