继上次踩完 h5 的坑后, 迎来了新需求, 需要生成 PDF, 内容包括封面, 目录, 然后就是正文, 正文的内容包括, 页眉, 页脚, 图表, 表格, 图片, 地图
最后实现的效果
封面
目录
主体内容
使用的框架
jspdf (放弃)
在网上搜到有关于 jspdf 的问题大致是不支持中文, 布局比较死板, 无法转换图片, 分页效果差. 然后就直接弃用了.
https://tcpdf.org/docs/ (第一版)
公司之前用的是这个插件, 但是这个 05 年后就没有再维护了, 我们第一版写的时候, 虽然按需求大致上的内容的都是实现了, 当然实现的过程痛苦, 首先所有的布局都只能使用 table 布局, 为什么不用 padding,margin 之类的呢, 因为不支持啊 (想哭), 然后目录的问题, 一开始我考虑的是前端可以通过计算每一个标题距离顶部的高度, 在通过生成的 PDF 页面的高度去计算, 标题所在的页面, but, 很不准, dom 计算的高度和最终 PDF 生成的高度差很多
https://wkhtmltopdf.org/ (最终版)
这个框架好啊, 简单好用, 基本支持前端的大部分 CSS, 除了目录有坑 (只有低版本支持分页, 我们现在用的是 wkhtmltopdf 0.12.3 版本), 封面需要单独写一个页面, 目录只要命令就能生成, 下面是核心代码
wkhtmltopdf --page-width 210mm --page-height 297mm --margin-top 15mm --header-left "这里是你的表头啦左边啦" --header-right "[date] [time] 机密文件请勿外传" --header-line --header-spacing 3 --footer-spacing 3 --footer-center "- 第 页 -" cover 这里是你提前写好的封面的地址 toc --toc-header-text "目录" 这里是你要生成 PDF 的地址 D:\\1.PDF
需要注意的点
table 跨页的时候会被分割
生成的 PDF 在分页处如下的效果
明显的发现表格的一行被切成了两部分, 最后在网上找了许久的, 发现解决还蛮简单的只要在不想被分割的元素上面加一条属性就好了
- table{
- page-break-before: left;
- }
现在就很 perrfect 了
百度地图
我想把地图转成成图片, 但是通过百度地图返回的全部都是 HTML, 而且里面的地图图片全部都是一张一张拼起来的, 就算是通过 html2canvas 截屏也不行. 最后让后端查看百度地图的文档, 直接输出地图的 PNG 的链接过来.
echarts 图表
因为图表是 cavans, 所以我们要将它转换成图片赋值给一个 img 标签
- let echartKLine = echarts.init(this.$el.querySelector('.js-kline'));
- echartKLine.setOption(_option);
- $("#"+this.mykey).attr("src",echartKLine.getDataURL())// 通过 getDataURL 的方法
水印
水印找了一种简单的方法, 就是给整个 PDF 的最外层, 通过 background 的方法平铺.
- .pdfContainer{
- background-image: url('背景图片地址');
- background-size: 300px;
- }
你本地的效果的是三列水印, 这也是你期望的效果, 但最后出来的效果可能只有两列
所以设置的时候要根据实际生成 PDF 的尺寸去调整水平平铺的样式, 打开开发者调试工具, 将页面的宽度调整到和生成 PDF 后的样式差不多的宽度 (也就是上面两条的情况), 然后调样式, 效果更佳哦
来源: https://juejin.im/post/5c122a766fb9a049fd0fb813