前端技术使网页生成PDF预览并下载

180 阅读1分钟

前端技术使网页生成PDF预览并下载,使用jsPDFhtml2Canvas,调用getPdfFun()即可。

 import {createApp, reactive, toRefs} from "vue";
 import jsPDF from "jspdf";
 import html2Canvas from "html2canvas";
 setup() {
     const state = reactive({
         htmlTitle: 'PDF文件名',
         Height: document.documentElement.clientHeight - 180,
         pdfProgress: 1,
         pdfPage: 1,
         pdfTotal: null,
         type: '01', // 01预览 02下载
         pdfContent: { content: '我是内容' },
         isDownloaded: false, // 是否生成PDF
         isOver: false, // 是否生成完毕
         a4Width: 415.28,
         // a4Width: 595.28,
         a4Height: 841.89,
         pdf: null,
         canvas: [],
         a4HeightRef: 0,
         position: 0,
         leftHeight: 0,
         pageFooter: null,
         canvasFooter: null,
         pageTitle: null,
         canvasTitle: null,
         canvasIndex: 0,
         pageData: null,
         isAddPage: false,
         canvas1: null,
         list: [],
     })
     const getPdfFun = () => {
         // 初始化PDF
         state.pdf = new jsPDF('', 'pt', 'a4')
         state.pdf.page = 1
         state.pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen')
         state.isDownloaded = true
         if (state.type === '01') {
             console.log(state.pdf, 'pdfthis');
             getPdf(state.htmlTitle, true)
         } else if (state.type === '02') {
             getPdf(state.htmlTitle, false)
         }
     };
     const getPdf = async (title, show) => {
         // 生成页眉图片
         state.canvasTitle = await html2Canvas(document.getElementById('title'))
         state.pageTitle = state.canvasTitle.toDataURL('image/jpeg', 1.0)
         // 生成内容 6个案件点的图片
         const doms = document.getElementsByClassName('casepoint')
         console.log(doms, 'doms');
         for (let i = 0; i < doms.length; i++) {
             if (doms[i]) {
                 const canvas = await html2Canvas(doms[i], {
                     allowTaint: true,
                     scale: 2
                 })
                 state.canvas.push(canvas)
             }
         }
         state.canvas1 = document.createElement('canvas')
         // 一页pdf显示html页面生成的canvas高度; -300为了每页PDF头部和底部留有空位
         state.a4HeightRef = Math.floor(state.canvas[0].width / state.a4Width * state.a4Height)-200;
         state.position = 0
         addPage()
         for (let canvasIndex = 0; canvasIndex < state.canvas.length; canvasIndex++) {
             state.position = 0
             // 未生成pdf的html页面高度
             state.leftHeight = state.canvas[canvasIndex].height
             createImpl(state.canvas[canvasIndex])
         }
         const that = this
         // 根据生成的页数,给每一页PDF加上页码
         state.isAddPage = true
         for (let page = 0; page <= state.pdfProgress; page++) {
             state.canvasFooter = await html2Canvas(document.getElementById('footer'))
             state.pageFooter = state.canvasFooter.toDataURL('image/jpeg', 1.0)
             state.pdf.setPage(page)
             if (state.pdfPage < state.pdfProgress) {
                 state.pdfPage++
             }
             // 添加页眉
             state.pdf.addImage(state.pageTitle, 'JPEG', 90, 40, state.a4Width, (state.a4Width / state.canvasTitle.width * state.canvasTitle.height).toFixed(2) / 1)
             // 添加页码
             state.pdf.addImage(state.pageFooter, 'JPEG', 90, state.a4Height-40, state.a4Width, (state.a4Width / state.canvasFooter.width * state.canvasFooter.height).toFixed(2) / 1)
         }
         // 所有内容都生成完毕
         if (!show) {
             // 直接下载
             that.pdf.save(title + '.pdf')
             that.isOver = true
         } else {
             // 在新窗口查看 pdf文件
             window.open(that.pdf.output('bloburl'))
             that.isOver = true
         }
         that.init();
     };
     const createImpl = async (canvas) => {
         console.log('这页PDF剩余的高度', state.a4LeftHeight)
         console.log('canvas剩余的高度', state.leftHeight)
         console.log('canvas开始截取的位置高度', state.position)
         if (state.leftHeight > 0) {
             if (state.leftHeight > state.a4LeftHeight) {
                 var checkCount = 0
                 var i = state.position + state.a4LeftHeight
                 // 从定好的高度页面,底部开始循环遍历canvas的每个点,找到可以截断的地方
                 for (i; i >= state.position; i--) {
                     var count = 0
                     var isWrite = true
                     for (var j = 0; j < canvas.width; j++) {
                         var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data
                         // 如果该单位的颜色不是白色c[0]  c[1]  c[2] 分别代表r g b 255
                         if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) {
                             count++
                         }
                         // 如果这行有连续20个单位都不是白色,退出当前循环
                         if (count > 20) {
                             isWrite = false
                             break
                         }
                     }
                     // 如果有连续10行都是白色的,canvas在这里可以截断了
                     if (isWrite) {
                         checkCount++
                         if (checkCount >= 20) {
                             break
                         }
                     } else {
                         checkCount = 0
                     }
                 }
                 state.height = i - state.position
                 if (state.height <= 0) { // 没找到截断点,新增一页PDF
                     // PDF剩余可用高度
                     state.a4LeftHeight = (state.a4HeightRef - 150).toFixed(2) / 1
                     // 先添加一张PDF
                     state.pdf.addPage()
                     state.pdfProgress = state.pdfProgress + 1
                     console.log('新增一页PDF  state.pdfProgress', state.pdfProgress)
                     state.height = state.leftHeight
                     createImpl(canvas)
                     return
                 }
             } else {
                 state.height = state.leftHeight
             }
             state.canvas1.width = canvas.width
             state.canvas1.height = state.height
             var ctx = state.canvas1.getContext('2d');
             ctx.drawImage(canvas, 0, state.position, canvas.width, state.height, 0, 0, canvas.width, state.height)
             console.log('canvas截断的位置', state.position, state.height)
             console.log('PDF生成的位置', state.a4HeightRef - state.a4LeftHeight, state.height)
             state.list.push(state.canvas1.toDataURL('image/jpeg', 1.0));
             state.pdf.addImage(state.canvas1.toDataURL('image/jpeg', 1.0), 'JPEG', 90, state.a4Width / state.canvas1.width * (state.a4HeightRef - state.a4LeftHeight)+26, state.a4Width, state.a4Width / state.canvas1.width * state.height)
             state.leftHeight -= state.height
             state.position += state.height
             state.a4LeftHeight -= state.height + 50
             if (state.leftHeight > 0) { // 第i个canvas还未截取完毕
                 await createImpl(canvas)
                 console.log(5555555555);
             }
         }
     };
     const addPage = async () => {
         // PDF页面剩余的高度
         state.a4LeftHeight = (state.a4HeightRef - 150).toFixed(2) / 1
     };
     const init = () => {
         state.pdf = null;
         state.canvas = [];
         state.isAddPage = false;
         state.pdfProgress = 1;
         state.pdfPage = 1;
         state.pdfTotal = null;
         state.canvas1 = null;
     }
     return {
         ...toRefs(state),
         getPdfFun,
     }
 }