前端一行代码生成数千页PDF,dompdf.js新增分页功能

内容分享2小时前发布
0 0 0

前端 #开源 #TypeScriptdompdf.js 是作者开源的前端 PDF 生成库。可以纯前端将 html 生成为非图片式的,可编辑,小体积的 PDF 文件。上一篇文章
https://juejin.cn/post/7559886023661649958 有做相关介绍。之前的版本只能生成单页 PDF,许多开发者反馈有生成多页 PDF 的需求,作者花了点时间在 V1.1.0 版本新增了分页功能,
可以将 html 页面生成为多页 PDF 文件

代码示例

import dompdf from "dompdf.js";

dompdf(document.querySelector("#capture"), { pagination: true }).then(function ( blob ) { //文件操作 });

实现效果如下(数千页 PDF):

当然,生成数千页的 PDF 是超级极端的情况才能达成,决定能生成多少页 PDF 的,要看文件大小,如果是纯文字 PDF,就能生成更多的页数,反之如果 PDF 中有图片,生成的页数就会少

1. 在线体验

dompdfjs.lisky.com.cn

2. Git 仓库地址 (欢迎 Star⭐⭐⭐)

github.com/lmn1919/dom…

gitee.com/liu-facai/d…

3.版本新功能特性

1. 分页功能-精准的页面分割

图片分页效果

左右布局分页效果

文本分页效果

复杂表格分页效果

2. 自定义页眉页脚

可以设置页眉页脚的高度,内容,字体大小,字体颜色等。

3. PDF 密码、操作权限设置,PDF 压缩

4.分页实现原理

dompdf.js 是如何将 html 页面生成为多页 PDF 文件的?

1.

大致的结构为:

{
bounds: {height: 1303.6875, left: 8, top: -298.5625, width: 1273},
elements: [
        {
        bounds: {left: 8, top: -298.5625, width: 1273, height: 1303.6875},
        elements: [
                {
                bounds: {left: 8, top: -298.5625, width: 1273, height: 1303.6875},
                elements: [
                        {styles: CSSParsedDeclaration, textNodes: Array(1), elements: Array(0), bounds: Bounds, flags: 0},
                        {styles: CSSParsedDeclaration, textNodes: Array(1), elements: Array(0), bounds: Bounds, flags: 0},
                        ...
                ],
                flags: 0,
                styles: {backgroundClip: Array(1), backgroundColor: 0, backgroundImage: Array(0), backgroundOrigin: Array(1), backgroundPosition: Array(1), …},
                textNodes: []
                }
        ],
        flags: 0,
        styles: CSSParsedDeclaration {backgroundClip: Array(1), backgroundColor: 0, backgroundImage: Array(0), backgroundOrigin: Array(1), backgroundPosition: Array(1), …},
        textNodes: []
        }
],
flags: 4,
styles: CSSParsedDeclaration {backgroundClip: Array(1), backgroundColor: 0, backgroundImage: Array(0), backgroundOrigin: Array(1), backgroundPosition: Array(1), …},
textNodes: []
}

2.

列如一个 textNodes 的位置信息是这样的:

{
 bounds: {left: 8, top: 1115, width: 850, height: 24},
 text: "这是一个文本节点"
}

如果我们要按照 a4 纸张的高度(1123px)来分页,那么当文本节点的 top 加上 height 大于 1123px 时,而 top 的值 1115px 小于 1123px,那么这个文本节点就会分割到第二页。并且 top 值会重置为 0,后续项的 top 值也会减少相应的值,确保元素位置的准确性。

1.

列如绘制文字:

jspdf.text("这是一个文本节点", 1115, 8);

绘制图片:

jspdf.image(img, x, y, width, height);

5.使用文档

安装:

npm install dompdf.js --save

CDN 引入:

<script src="https://cdn.jsdelivr.net/npm/dompdf.js@latest/dist/dompdf.js"></script>

基础用法

import dompdf from "dompdf.js";

dompdf(document.querySelector("#capture"), options) .then((blob) => { const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "example.pdf"; document.body.appendChild(a); a.click(); }) .catch((err) => { console.error(err); });

PDF 分页渲染

默认情况下,dompdf 会将整个文档渲染到单页中。

您可以通过设置 pagination 选项为 true 来开启分页渲染。通过 pageConfig 字段自定义页眉页脚的尺寸,内容,字体颜色/大小,位置等信息。

超级重大!!!!超级重大!!!!超级重大!!!!超级重大!!!!超级重大!!!!

需要将要生成 PDF 的 dom 节点设置为对应的页面宽度(px),列如 a4要设置宽度为794px,这里是页面尺寸对照表,请点击查看

<div
    id="capture"
    style="width:794px"
    >

</div>
import dompdf from "dompdf.js";

dompdf(document.querySelector("#capture"), { pagination: true, format: "a4", pageConfig: { header: { content: "这是页眉", height: 50, contentColor: "#333333", contentFontSize: 12, contentPosition: "center", padding: [0, 0, 0, 0], }, footer: { content: "第${currentPage}页/共${totalPages}页", height: 50, contentColor: "#333333", contentFontSize: 12, contentPosition: "center", padding: [0, 0, 0, 0], }, }, }) .then((blob) => { const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "example.pdf"; document.body.appendChild(a); a.click(); }) .catch((err) => { console.error(err); });

更精准的分页控制- divisionDisable 属性

如果您不希望某个容器在分页时被拆分时,为该元素添加 divisionDisable 属性,跨页时它会整体移至下一页。

<img
  src=""
  alt="PDF Generation Example"
  crossorigin="anonymous"
  divisionDisable
/>

右边为使用 divisionDisable 属性的效果

options 参数

| 参数名 | 必传 | 默认值 | 类型 | 说明 | | —

| useCORS | 否 | false | boolean | 允许跨域资源(需服务端 CORS 配置) | | backgroundColor | 否 | 自动解析/白色 | string | null | 覆盖页面背景色;传 null 生成透明背景 | | fontConfig | 否 | –

| encryption | 否 | 空配置 | object | PDF 加密配置,属性 userPassword 用于给定权限列表下用户的密码;属性 ownerPassword 需要设置 userPassword 和 ownerPassword 以进行正确的身份验证;属性 userPermissions 用于指定用户权限,可选值为 ['print', 'modify', 'copy', 'annot-forms'] | | precision | 否 | 16 | number | 元素位置的精度 | | compress | 否 | false | boolean | 是否压缩是否压缩 PDF | | putOnlyUsedFonts | 否 | false | boolean | 仅将实际使用的字体嵌入 PDF | | pagination | 否 | false | boolean | 开启分页渲染 | | format | 否 | 'a4' | string | 页面规格,支持 a0–a10、b0–b10、c0–c10、letter 等 | | pageConfig | 否 | 见下表 | object | 页眉页脚配置 |

pageConfig 字段:

| 参数名 | 默认值 | 类型 | 说明 | | —

| header | 见下表 pageConfigOptions | object | 页眉设置 | | footer | 见下表 pageConfigOptions | object | 页脚设置 |

pageConfigOptions 字段:

| 参数名 | 默认值 | 类型 | 说明 | | —

| content | 页眉默认值为空,页脚默认值为${currentPage}/${totalPages} | string | 文本内容,支持 ${currentPage}、${totalPages},${currentPage}为当前页码,${totalPages}为总页码 | | height | 50 | number | 区域高度(px) | | contentPosition | 'center' | string | [number, number] | 文本位置枚举 center、centerLeft 、centerRight、centerTop、centerBottom、leftTop、leftBottom、rightTop、rightBottom 或坐标 [x,y] | | contentColor | '#333333' | string | 文本颜色 | | contentFontSize | 16 | number | 文本字号(px) | | padding | [0,24,0,24] | [number, number, number, number] | 上/右/下/左内边距(px) |

字体配置( fontConfig )字段:

| 字段 | 必传 | 默认值 | 类型 | 说明 | | —

| fontFamily | 是(启用自定义字体时) | '' | string | 字体家族名(与注入的 .ttf 同名) | | fontBase64 | 是(启用自定义字体时) | '' | string | .ttf 的 Base64 字符串内容 |

乱码问题-字体导入支持

由于 jspdf 只支持英文,所以其他语言会出现乱码的问题,需要导入对应的字体文件来解决,如果需要自定义字体,在 这里 将字体 tff 文件转化成 base64 格式的 js 文件,中文字体推荐使用 思源黑体 ,体积较小。在代码中引入该文件即可。

<script type="text/javascript" src="./SourceHanSansSC-Normal-Min-normal.js"></script>

<script>

dompdf(document.querySelector('#capture'), { useCORS: true, fontConfig: { fontFamily: 'SourceHanSansSC-Normal-Min', fontBase64: window.fontBase64 } }) .then(function (blob) { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'example.pdf'; document.body.appendChild(a); a.click(); }) .catch(function (err) { console.error(err); }); </script>

绘制渐变色、阴影等复杂样式-foreignObjectRendering 使用

在 dom 十分复杂,或者 pdf 无法绘制的情况(列如:复杂的表格,边框阴影,渐变等),可以思考使用 foreignObjectRendering。给要渲染的元素添加 foreignObjectRendering 属性,就可以通过 svg 的 foreignObject 将它渲染成一张背景图插入到 pdf 文件中。

但是,由于 foreignObject 元素的渲染依赖于浏览器的实现,因此在不同的浏览器中可能会有不同的表现。所以,在使用 foreignObjectRendering 时,需要注意以下事项:

  1. foreignObject 元素的渲染依赖于浏览器的实现,因此在不同的浏览器中可能会有不同的表现。
  2. IE 浏览器完全不支持,推荐在 chrome 和 firefox,edge 中使用。
  3. 生成的图片会导致 pdf 文件体积变大。

示例

<div style="width: 100px;height: 100px;" foreignObjectRendering>

<div style="width: 50px;height: 50px;border: 1px solid #000;box-shadow: 2px 2px 5px rgba(0,0,0,0.3);background: linear-gradient(45deg, #ff6b6b, #4ecdc4);" >

这是一个 div 元素 </div>

</div>

浏览器兼容性

该库应该可以在以下浏览器上正常工作(需要 Promise polyfill):

  • Firefox 3.5+
  • Google Chrome
  • Opera 12+
  • IE9+
  • Safari 6+
© 版权声明

相关文章

暂无评论

none
暂无评论...