vue + jsPdf+html2canvas导出pdf

main.js

import htmlToPdf from “@/util/htmlToPdf”

Vue.use(htmlToPdf)

htmlToPdf.js

import html2canvas from “html2canvas”
import JsPDF from “jspdf”
/**

  • @param ele要生成 pdf 的DOM元素(容器)

  • @param el_class 不能分割的元素

  • @param pdfFileName PDF文件生成后的文件名字

  • */
    export default {
    install(Vue, options) {
    Vue.prototype.getPdfFromHtml = (ele, el_class, pdfFileName) => {
    //a4纸的尺寸[595.28,841.89],单位像素,html页面生成的canvas在pdf中图片的宽高
    //ele 要导出的容器 el_class标记不能分割的元素 pdfFileName导出的文件名
    let A4_WIDTH = 595.28
    let A4_HEIGHT = 841.89

         function splitPage(dom) {
             const pageOffsetTop = dom.offsetTop
             const pageOffsetWidth = dom.offsetWidth
             const pageOffsetHeight = dom.offsetHeight
             const $unitElements = dom.querySelectorAll('.' + el_class) //标记不能分割的元素
             const peerPageHeight = pageOffsetWidth / A4_WIDTH * A4_HEIGHT // 获取缩放后的一页页面高度
             const pages = []
             // 遍历最小单元格
             // 获取单元格底部距离顶部的高度 top,以及 offsetTop
             // 根据 top 值,算出该单元格的页码,放入数组 pages
             $unitElements.forEach($element => {
                 const offsetTop = $element.offsetTop - pageOffsetTop
                 let pagesIndex = Math.ceil(offsetTop / peerPageHeight)
                 for (let i = 0; i < pagesIndex; i++) {
                     if (typeof pages[i] === 'undefined') {
                         pages[i] = [{
                             offsetTop: peerPageHeight * i,
                             top: peerPageHeight * (i + 1)
                         }]
                     }
                 }
    
                 const top = offsetTop + $element.offsetHeight
                 const pageIndex = Math.ceil(top / peerPageHeight)
    
                 // 新的一页
                 console.log(pagesIndex,12221)
                 if (pageIndex > pagesIndex) {
                     let peerIndex = Math.ceil($element.offsetHeight / peerPageHeight)
                         pages[pagesIndex - 1][0].top=offsetTop
                         for (let i = 0; i < peerIndex; i++) { 
                         pages[pagesIndex + i] = [{
                             top: (offsetTop+peerPageHeight)>pageOffsetHeight?pageOffsetHeight:offsetTop+peerPageHeight,
                             offsetTop: offsetTop
                         }]
                     }
    
                 }
    
             })
             let heightIndex=0
             let index=pages.length
             if(pages.length&&pages[pages.length-1][0].top<pageOffsetHeight){
                 heightIndex=Math.ceil((pageOffsetHeight-pages[pages.length-1][0].top)/peerPageHeight) 
             }
             for(let i=0;i<heightIndex;i++){
                 pages[index+i]=[{
                     top: (pages[index-1+i][0].top+peerPageHeight)>pageOffsetHeight?pageOffsetHeight:pages[index-1+i][0].top+peerPageHeight,
                     offsetTop: pages[index-1+i][0].top
                 }]
             }
             
             return pages
         }
         let eleW = ele.offsetWidth // 获得该容器的宽
         //   let eleH = ele.offsetHeight // 获得该容器的高
         let eleH = ele.scrollHeight // 获得该容器的高
         let eleOffsetTop = ele.offsetTop // 获得该容器到文档顶部的距离
         let eleOffsetLeft = ele.offsetLeft // 获得该容器到文档最左的距离
         var canvas = document.createElement("canvas")
         var abs = 0
         let win_in = document.documentElement.clientWidth || document.body.clientWidth // 获得当前可视窗口的宽度(不包含滚动条)
         let win_out = window.innerWidth // 获得当前窗口的宽度(包含滚动条)
         if (win_out > win_in) {
             // abs = (win_o - win_i)/2;    // 获得滚动条长度的一半
             abs = (win_out - win_in) / 2 // 获得滚动条宽度的一半
         }
         canvas.width = eleW * 2 // 将画布宽&&高放大两倍
         canvas.height = eleH * 2
         var context = canvas.getContext("2d")
         context.scale(2, 2) // 增强图片清晰度
         context.translate(-eleOffsetLeft - abs, -eleOffsetTop)
    
    
         html2canvas(ele, {
             dpi: 300,
             useCORS: true //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
         }).then(canvas => {
             var contentWidth = canvas.width
             var contentHeight = canvas.height
             console.log('canvars宽:' + contentWidth + '高:' + contentHeight)
             //一页pdf显示html页面生成的canvas高度;
             var pageHeight = (contentWidth / (A4_WIDTH - 3)) * A4_HEIGHT // 这样写的目的在于保持宽高比例一致 pageHeight/canvas.width = a4纸高度/a4纸宽度// 宽度和canvas.width保持一致
             //未生成pdf的html页面高度
             var leftHeight = contentHeight
             //页面偏移
             var position = 20
             var imgWidth = A4_WIDTH
             var imgHeight = (A4_WIDTH / contentWidth) * contentHeight
             console.log('缩放后图片宽:' + A4_WIDTH + '高:' + imgHeight)
    
             var pageData = canvas.toDataURL("image/jpeg", 1.0)
             var pdf = new JsPDF("", "pt", "a4")
             //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
             let pages = splitPage(ele)
             // console.log(JSON.stringify(pages))
             //当内容未超过pdf一页显示的范围,无需分页
             if (leftHeight < pageHeight - 40) {
                 //在pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置在pdf中显示;
                 pdf.addImage(pageData, 'JPEG', 10, 20, imgWidth - 20, imgHeight - 40);
                 pdf.save(pdfFileName + ".pdf")
             } else if (pages.length > 1) {
                 console.log(pages)
                 pages.forEach((page, index) => {
                     const {
                         offsetTop
                     } = page[0]
                     const {
                         top
                     } = page[page.length - 1]
                     let img = new Image();
                     img.src = pageData;
                     //生成canvas
                     let canvas1 = {}
                     let num = 1
                     // if(index>0){
                     //占一页的高度比
                     num = (top - offsetTop) / ((A4_HEIGHT - 40) / ((A4_WIDTH - 20) / contentWidth))
                     // }
                     canvas1['canvas' + index] = document.createElement('canvas');
                     var ctx = canvas1['canvas' + index].getContext('2d');
                     var createw = document.createAttribute('width');
                     var createh = document.createAttribute('height');
                     createw.nodeValue = contentWidth;
                     createh.nodeValue = top - offsetTop;
                     canvas1['canvas' + index].setAttributeNode(createh);
                     canvas1['canvas' + index].setAttributeNode(createw);
                     img.onload = () => {
                         if (index > 0) {
                             pdf.addPage()
                         }
                         // if(num>1){
    
                         //     let pageHeight=top-offsetTop
                         //     while (pageHeight > 0) {
                         //         tx.drawImage(img, 0, offsetTop, contentWidth, top, 0, 0, contentWidth, top);
                         //         var base64Result = canvas1['canvas' + index].toDataURL("image/jpeg", 1.0)
                         //         pdf.addImage(base64Result, 'JPEG', 10, 20, A4_WIDTH - 20, (A4_HEIGHT-40)*num)
    
                         //         pdf.addImage(pageData, "JPEG", 10, position, imgWidth - 20, imgHeight)
                         //         pageHeight -= pageHeight
                         //         position -= (A4_HEIGHT)
                         //         //避免添加空白页
                         //         if (pageHeight > 0) {
                         //             pdf.addPage()
                         //         }
                         //     }
                         // }else{
                         ctx.drawImage(img, 0, offsetTop, contentWidth, top, 0, 0, contentWidth, top);
                         var base64Result = canvas1['canvas' + index].toDataURL("image/jpeg", 1.0)
                         pdf.addImage(base64Result, 'JPEG', 10, 20, A4_WIDTH - 20, (A4_HEIGHT - 40) * num)
                         // }
                         if (index == pages.length - 1) {
                             pdf.save(pdfFileName + ".pdf")
                         }
                     }
                 })
             } else {
                 // 分页
                 while (leftHeight > 0) {
                     pdf.addImage(pageData, "JPEG", 10, position, imgWidth - 20, imgHeight)
                     leftHeight -= pageHeight
                     position -= (A4_HEIGHT)
                     //避免添加空白页
                     if (leftHeight > 0) {
                         pdf.addPage()
                     }
                 }
                 pdf.save(pdfFileName + ".pdf")
    
             }
    
         })
     }
    

    }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值