js html导出pdf,js html打印

安装以下5个依赖包

npm i html2canvas

npm i jspdf
npm i print-js

npm i jszip

npm i file-saver

新建文件pdfUtils.js

import {ElLoading} from "element-plus";
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
import printJS from "print-js";
import JSZip from "jszip";
import FileSaver from "file-saver";

/**
 * @desc html转canvas
 * @param {HTMLElement} element 需要转换的html节点
 * @auth roffer
 * @date 2024/10/23 10:12
 */
export const htmlToCanvas = async (element) => {
    const oldOffsetHeight = element.offsetHeight
    //是否包含滚动条
    const isScroll = element.scrollHeight > oldOffsetHeight
    if (isScroll) {
        //如果包含滚动条,重新设置元素的高度,让其显示完整,因为html2canvas不能输出滚动条以外的内容
        element.style.height = element.scrollHeight + "px"
    }

    const options = {
        // useCORS: true,
        // dpi: window.devicePixelRatio * 1,  //dpi属性的值为192,表示图像的分辨率
        // scale: 4, //scale属性的值为2,表示图像的缩放比例。
        // backgroundColor: "#F1F6FE"  //backgroundColor属性的值为"#F1F6FE",表示图像的背景颜色。
    }

    const canvas = await html2canvas(element, options)
    // const data = canvas.toDataURL('image/png')

    if (isScroll) {
        //处理完成之后还原之前的高度
        element.style.height = oldOffsetHeight + "px"
    }

    return canvas
}

/**
 * @desc 打印html节点
 * @param {String} selector 需要转换的html节点选择器: .xxx #xxx
 * @auth roffer
 * @date 2024/10/23 10:33
 */
export const printHTML = async (selector) => {
    const element = document.querySelector(selector)
    const canvas = await htmlToCanvas(element)
    // const pdfFile = await html2PDF(selector)
    printJS({
        // printable: pdfFile, // 指定要打印内容的元素
        // type: 'pdf',//指定打印的类型,pdf、image、html、json、raw-html
        // printable: element, // 指定要打印内容的元素
        printable: canvas, // 指定要打印内容的元素
        type: 'html',//指定打印的类型,pdf、image、html、json、raw-html
        // 不打印页眉和页脚,以及解决打印预览多出来的一页空白页,设置:body {margin:0;padding:0}
        style: '@page {size: auto;margin: 0 10mm} body {margin:0;padding:0}',
        // honorColor: true,// 是否打印彩色文本
        // scanStyles: true,
        // base64:true,//当type为'image'时,将图像转换为base64格式并返回。
        // style: '@import "@/components/printTemplates/components/order/windowBinding.scss";' // 指定打印样式文件
        // targetStyles: ['*'], // 允许打印所有样式属性
        // documentTitle: '文档标题',//指定输出的文档标题。
        // header: '统计图',
        // css: new URL('@/components/printTemplates/components/order/windowBinding.scss', import.meta.url).href
    })
}

/**
 * html导出pdf
 * @param {Object} option 参数对象
 * @param {String} option.selector 需要导出的html节点选择器: .xxx #xxx 如果匹配到多个元素,则会导出多个文件
 * @param {Array} option.nameList 导出的文件名称,传递一个数组,因为传递的元素可能会有多个,则会生成多个pdf文件。举例:['name1.pdf','name2,pdf']
 * @param {Boolean} option.zip 是否将pdf文件导出zip,默认false
 * @auth Roffer
 * @date 2024/4/19 15:26
 *
 */
export const html2PDF = async (option) => {
    const loadingInstance = ElLoading.service({
        lock: true,
        text: '生成中,请稍后...',
        background: 'rgba(0, 0, 0, 0.7)',
    })

    const {selector,nameList,zip,zipName} = {
        zip: false,
        zipName:'pdfs.zip',
        ...option
    }

    // 创建JSZip实例
    let zipPackage = new JSZip()

    //获取dom节点
    const elementList = document.querySelectorAll(selector)

    for (let i = 0; i < elementList.length; i++) {
        // 新建jsPDF实例
        const pdf = new jsPDF('p', 'px', 'a4')

        const element = elementList[i]

        //使用html2Canvas插件将dom节点转化成base64
        const canvas = await htmlToCanvas(element)

        const elementWidth = element.offsetWidth
        const elementHeight = element.scrollHeight > element.offsetHeight ? element.scrollHeight : element.offsetHeight
        // const elementWidth = canvas.width
        // const elementHeight = canvas.height

        //图片数据
        let imgData = canvas.toDataURL('image/jpeg', 1.0)
        //图片宽度
        const imgWidth = pdf.internal.pageSize.getWidth()
        //图片高度
        const imgHeight = (imgWidth / elementWidth) * elementHeight;
        //一页高度
        const pageHeight = Math.ceil(pdf.internal.pageSize.getHeight())
        let position = 0

        if (imgHeight <= pageHeight) {
            //不足或者刚好够一页的情况
            pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight)
        } else {
            //超出一页的情况,循环判断如果图片高度+移动后的一个单位页高度还小于总高度,说明还有分页,继续进行下一个分页
            while (imgHeight + Math.abs(position) < elementHeight) {
                pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight)
                position -= pageHeight

                //处理边界空白情况,防止多出来一个空白页
                if (imgHeight + Math.abs(position) < elementHeight) {
                    pdf.addPage()
                }
            }
        }

        if(zip){
            // 将blob添加到zip文件中
            zipPackage.file(nameList[i], pdf.output('blob'))
        }else{
            // 保存PDF
            pdf.save(nameList[i])
        }
    }

    // 使用JSZip将所有PDF打包成ZIP文件并下载
    zip && zipPackage.generateAsync({type: "blob"}).then(function (content) {
        FileSaver.saveAs(content, zipName)
    })

    loadingInstance.close()
}

调用测试

import {printHTML,html2PDF} from './pdfUtils'

//执行打印
const doPrint = () => {
  printHTML('#printTemplate')
}

//导出pdf文件
const doExport = () => {
  const nameList = ['name1.pdf','name2.pdf']
  html2PDF({
    selector: '.template',
    nameList,
    zip: true,
    zipName: 'test.zip',
  })
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

roffer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值