乐趣区

【Vue 实践】页面生成 pdf 文件-01

介绍
为了找工作,花了七八天完成了自己的线上简历,结果发现并没有人来看这东西。
说实话,这个是自己的第一个前后端项目,自我感觉还好,结果根本没人在意,一定是我做得太差,那就得好好改这个项目,增加功能。
新增的下载简历效果图:

广告:Github 地址三个月工作经验找前端工作

规范化
在开始动工之前,需要考虑自己做什么了,没有接触大公司的规范的开发流程,那也得自己编一个出来。
如果有了解如何进行规范化开发的,希望能够在下方评论处给予我一些参考链接
创建 Issue

想一下目前要做的事情,提上对应的 Issue,再加上对应的标签 TODO、Feature;为这个功能找到处理者;将其添加到对应的 看板
修改看板

将所有的需求添加至 To do,再将要立即处理的移至 In progress
创建分支

准备采用 Github Flow 的工作流,首先创建一个分支,在克隆到本地
git branch -av
# 创建本地分支并建立关联
git checkout -b feature/download_pdf origin/feature/download_pdf
功能开发
安装依赖
选取的是想法 1,利用 canvas 来实现,安装相关的依赖
npm i html2canvas -S
npm i jspdf -S
注册功能
这个功能将会被注册为全局的插件进行调用,按照习惯,将其放入 plugins 文件夹下,引入依赖,注册一套走起:
// 创建插件 pdf.js
// 引入依赖
import Vue from “vue”;
import html2canvas from “html2canvas”;
import jspdf from “jspdf”;

const PDF = {};
// eslint-disable-next-line no-unused-vars
PDF.install = function(Vue, options) {
Vue.prototype.$pdf = function() {
// eslint-disable-next-line no-console
console.log(“hello pdf”);
};
};

Vue.use(PDF);

export default PDF;

// 在 main.js 中注册插件
import “./plugins/pdf”;

// 在对应的地方触发方法
this.$pdf(); // hello world
转为 Canvas
首先需将 HTML 转为 Canvas,看一下 html2canvas 是怎么处理的:

很简单的语法,获取 DOM 就可以了。
增加 ref 属性
<share-page v-if=”!shareLoading” ref=”pdfPage”></share-page>
将 DOM 传递到 触发事件中
<script>
export default {
methods: {
download() {
this.$pdf(this.$refs.pdfPage.$el);
}
}
}
</script>
测试 DOM 结果
Vue.prototype.$pdf = function(dom) {
// eslint-disable-next-line no-console
console.log(dom); // 得到期望结果
};
使用 html2canvas
Vue.prototype.$pdf = function(dom) {
html2canvas(dom).then(canvas => {
dom.appendChild(canvas);
});
};
前往页面查看,可以得到一个完美效果的 Canvas
打印为 PDF
接下来是处理成 pdf,看一下官网它是怎么处理的:

看起来很简单,提供一张图片(base64),然后就可以生成了。我们知道 canvas 是可以转为 图片(base64)的,示例中给的图片格式是 jpeg,所以 canvas 也处理为 jpeg:
html2canvas(dom).then(canvas => {
const jpeg = canvas.toDataURL(“image/jpeg”);
const doc = new JsPDF();

doc.setFontSize(40);
doc.text(35, 25, “ 简历 ”);
doc.addImage(jpeg, “JPEG”, 15, 40, 180, 160);
doc.save(“ 简历 ”);
});
好了,测试一下结果吧:

简历是生成了,但是未免有些不对劲,看一下 文档 重新搞吧:
html2canvas(dom).then(canvas => {
const [AWidth, AHeight] = [595.28, 841.89]; // a4
const {width: CWidth, height: CHeight} = canvas;
const PWidth = AWidth;
const PHeight = (AWidth / CWidth) * CHeight;
const jpeg = canvas.toDataURL(“image/jpeg”, 1.0);
const doc = new JsPDF(“”, “pt”, “a4”);

doc.addImage(jpeg, “JPEG”, 0, 0, PWidth, PHeight);
doc.save(“ 简历 ”);
});
一顿操作发现简历长度超过 a4 纸的高度了,那就再给它增加一页,此处 参考:
Vue.prototype.$pdf = function(dom, user) {
html2canvas(dom).then(canvas => {
const [AWidth, AHeight] = [595.28, 841.89]; // a4
let position = 0;
let {width: CWidth, height: CHeight} = canvas;
const PWidth = AWidth;
const PHeight = (AWidth / CWidth) * CHeight;
const jpeg = canvas.toDataURL(“image/jpeg”, 1.0);
const doc = new JsPDF(“”, “pt”, “a4”);

if (CHeight < PHeight) {
doc.addImage(jpeg, “JPEG”, 0, 0, PWidth, PHeight);
} else {
while (CHeight > 0) {
doc.addImage(jpeg, “JPEG”, 0, position, PWidth, PHeight);
CHeight -= PHeight;
position -= AHeight;
if (CHeight > 0) {
doc.addPage();
}
}
}
doc.save(user);
});
好了,大功告成,成功结果在介绍中展示了。
最后,提交,review,合并分支,发布代码。
Bug
仅能算作勉强完成,分割时会导致连续的内容分开,这个感觉会耗时很久……
参考文档

html2canvas
jspdf
toDataURL

退出移动版