Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克

简介: Vue生成PDF文件攻略:html2canvas与jspdf联手,中文乱码与自动换行难题攻克

在做项目时有这么一个需求,需要将当前页面指定区域的内容导出pdf到本地。借助了两个插件分别是html2canvas.js和pdf.js来实现。使用过程中遇到的问题及解决方法

解决一些问题:


  • 导出按A4纸大小排列
  • 预留页面边距的问题
  • 内容过多自动分页的问题
  • 直接使用jspdf中文乱码的问题
  • 直接使用jspdf文本自动换行的问题


一、安装依赖
  • 将页面转换成图片
    html2canvas 的作用就是根据 DOM 生成对应的图片。它的屏幕截图是基于 DOM 的,因此可能不会 100% 精确到真实的表示,因为它不会生成实际的屏幕截图,而是基于页面上可用的信息构建屏幕截图。
npm install html2canvas --save
  • 将图片导出成PDF
    JSPDF是一个JavaScript库,用于生成PDF文档。它可以直接在浏览器中生成PDF,也可以通过Node.js在服务器端生成PDF。JSPDF具有高度的自定义性和可扩展性,可以用于各种PDF生成需求。
npm install jspdf --save


二、具体使用
1、页面中创建一个容器ref=“contenterPdf”
<template>
<div>
    <div ref="contenterPdf">
        <img alt="Vue logo" src="../assets/logo.png" />
        <div>JSPDF是一个用于生成PDF文件的客户端JavaScript库。它提供了简单易用的API,使得我们可以在浏览器端创建PDF文件。相比于服务端生成PDF文件,使用JSPDF可以避免服务端的压力,并且能够实现更多的交互与设计效果。基于JSPDF,我们可以生成包括图表、表格、文字、图片、图形等各种元素的PDF文档,同时也可以设置字体、颜色、边框等多种属性来调整文档的样式。</div>
    </div>
    <button @click="handleExport">导出PDF文件</button>
</div>
</template>
2、创建/utils/htmlToPdf.js文件
import html2canvas from "html2canvas";
import jsPDF from "jspdf";

export const downloadPDF = page => {
    html2canvas(page, {
        useCORS: true, //允许canvas画布内 可以跨域请求外部链接图片, 允许跨域请求。
        allowTaint: true, //允许跨域
        scale: 2, 设置放大倍数
        backgroundColor: '#ffffff'//背景色
    }).then((canvas)=> {
        canvas2PDF(canvas);
    })
};

const canvas2PDF = canvas => {
    // 新建JsPDF对象
    const PDF = new jsPDF({
        orientation: 'p', //参数: l:横向  p:纵向
        unit: 'mm', //参数:测量单位("pt","mm", "cm", "m", "in" or "px")
        format: 'a4', //A4纸
    })
    const ctx = canvas.getContext('2d')
    const a4w = 190
    const a4h = 277 //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
    const imgHeight = Math.floor(a4h * canvas.width / a4w) //按A4显示比例换算一页图像的像素高度
    let renderedHeight = 0

    while (renderedHeight < canvas.height) {
        let 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);

        // canvas转图片数据保留10mm边距
        PDF.addImage(page.toDataURL('image/jpeg', 0.2), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width));

        renderedHeight += imgHeight;

        //判断是否分页,如果后面还有内容,添加一个空页
        if (renderedHeight < canvas.height) {
            PDF.addPage()
        }
    }

    PDF.save("导出.pdf");
};
3、页面方法中调用
<script>
import { downloadPDF } from "@/utils/htmlToPdf.js"
export default {
    data() {
        return {};
    },
    methods: {
        handleExport() {
            downloadPDF(this.$refs.contenterPdf)
        },
    },
};
</script>
  • 页面效果

  • 导出效果

  • 导出多页的效果


三、解决jspdf中文乱码

如果是直接使用jsPDF生成pdf文件,中文是乱码。

PDF.text('JSPDF是一个用于生成PDF文件的客户端JavaScript库。它提供了简单易用的API,使得我们可以在浏览器端创建PDF文件。', 10, 100);

  • 解决方案

需要一个支持中文的字体ttf文件,可以在网上下载,也可以使用本地window/font/路径下的文件。

1、下载jspdf

里面有个fontconverter目录

2、双击打开fontconverter.html文件

选择你本地的ttf文件,点击“Create”按钮,会生成一个js文件。

3、将js文件放入自己的项目中

在页面中引入js文件

import '@/utils/simhei-normal.js'
4、设置字体
PDF.setFont('simhei')
PDF.text('JSPDF是一个用于生成PDF文件的客户端JavaScript库。它提供了简单易用的API,使得我们可以在浏览器端创建PDF文件。', 10, 100);


四、解决jspdf文本自动换行

上面乱码解决了,但是发现中文字不会自动换行。这个还需要进一步解决。

1、使用splitTextToSize解决

//文本内容
const reportTitle = 'JSPDF是一个用于生成PDF文件的客户端JavaScript库。它提供了简单易用的API,使得我们可以在浏览器端创建PDF文件。相比于服务端生成PDF文件,使用JSPDF可以避免服务端的压力,并且能够实现更多的交互与设计效果。基于JSPDF,我们可以生成包括图表、表格、文字、图片、图形等各种元素的PDF文档,同时也可以设置字体、颜色、边框等多种属性来调整文档的样式。'
//设置自动换行
const splitTitle = PDF.splitTextToSize(reportTitle, 190);
//添加文本内容
PDF.text(splitTitle, 10, 110);


五、添加页码

在导出多页的时候,希望在页面尾部添加页码。

这里可以通过页码尺寸计算。

//计算总页数
let pageCount = Math.ceil(canvas.height/imgHeight)

将上面的的方法改写一下:

const canvas2PDF = canvas => {
    // 新建JsPDF对象
    const PDF = new jsPDF({
        orientation: 'p', //参数: l:横向  p:纵向
        unit: 'mm', //参数:测量单位("pt","mm", "cm", "m", "in" or "px")
        format: 'a4', //A4纸
    })
    const ctx = canvas.getContext('2d')
    const a4w = 190
    const a4h = 272 //A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277,底部留5mm的页码显示位置,所以高度为272mm。
    const imgHeight = Math.floor(a4h * canvas.width / a4w) //按A4显示比例换算一页图像的像素高度
    let renderedHeight = 0
    //计算总页数
    const pageCount = Math.ceil(canvas.height/imgHeight)
    const page = document.createElement("canvas");
    page.width = canvas.width;
    while (renderedHeight < canvas.height) {
        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);
        // canvas转图片数据保留10mm边距
        PDF.addImage(page.toDataURL('image/jpeg', 0.2), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width));
        renderedHeight += imgHeight;
        // 计算当前页,及文字
        const pageNumberText = '第' + (renderedHeight/imgHeight) + '页,共' + pageCount + '页';
        // 设置中文字体
        PDF.setFont('simhei')
        // 设置文字大小
        PDF.setFontSize(8);
        // 设置文字颜色
        PDF.setTextColor('#999999');
        // 在页脚添加页码
        PDF.text(pageNumberText, (a4w/2), (a4h+16));
        //判断是否分页,如果后面还有内容,添加一个空页
        if (renderedHeight < canvas.height) {
            PDF.addPage()
        }
    }
    PDF.save("导出.pdf");
};

最后导出后的效果

目录
相关文章
|
3天前
|
人工智能 文字识别 数据挖掘
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
MarkItDown 是微软开源的多功能文档转换工具,支持将 PDF、PPT、Word、Excel、图像、音频等多种格式的文件转换为 Markdown 格式,具备 OCR 文字识别、语音转文字和元数据提取等功能。
47 9
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
|
7天前
|
JavaScript
jquery图片和pdf文件预览插件
EZView.js是一款jquery图片和pdf文件预览插件。EZView.js可以为图片和pdf格式文件生成在线预览效果。支持的文件格式有pdf、jpg、 png、jpeg、gif。
38 16
|
2月前
|
JavaScript 前端开发 安全
vue -- 指令 -- v-text/html/on/show/if/bind/for/model
【10月更文挑战第17天】Vue 指令是构建 Vue 应用的基础工具,掌握它们的特性和用法是成为一名优秀 Vue 开发者的重要一步。通过深入理解和熟练运用这些指令,可以打造出更加出色的前端应用。
80 50
|
2月前
|
Web App开发 前端开发 搜索推荐
创建HTML文件
【10月更文挑战第14天】创建HTML文件
60 4
|
2月前
|
Java Apache Maven
将word文档转换成pdf文件方法
在Java中,将Word文档转换为PDF文件可采用多种方法:1) 使用Apache POI和iText库,适合处理基本转换需求;2) Aspose.Words for Java,提供更高级的功能和性能;3) 利用LibreOffice命令行工具,适用于需要开源解决方案的场景。每种方法都有其适用范围,可根据具体需求选择。
|
2月前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
447 1
|
24天前
|
前端开发 测试技术 定位技术
如何利用HTML和CSS构建企业级网站的全过程。从项目概述到页面结构设计,再到HTML结构搭建与CSS样式设计,最后实现具体页面并进行优化提升,全面覆盖了网站开发的关键步骤
本文深入介绍了如何利用HTML和CSS构建企业级网站的全过程。从项目概述到页面结构设计,再到HTML结构搭建与CSS样式设计,最后实现具体页面并进行优化提升,全面覆盖了网站开发的关键步骤。通过实例展示了主页、关于我们、产品展示、新闻动态及联系我们等页面的设计与实现,强调了合理布局、美观设计及用户体验的重要性。旨在为企业打造一个既专业又具吸引力的线上平台。
48 7
|
24天前
|
前端开发 JavaScript 搜索推荐
HTML与CSS在Web组件化中的核心作用及前端技术趋势
本文探讨了HTML与CSS在Web组件化中的核心作用及前端技术趋势。从结构定义、语义化到样式封装与布局控制,两者不仅提升了代码复用率和可维护性,还通过响应式设计、动态样式等技术增强了用户体验。面对兼容性、代码复杂度等挑战,文章提出了相应的解决策略,强调了持续创新的重要性,旨在构建高效、灵活的Web应用。
32 6
下一篇
DataWorks