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

介绍

为了找工做,花了七八天完成了本身的线上简历,结果发现并无人来看这东西。javascript

说实话,这个是本身的第一个先后端项目,自我感受还好,结果根本没人在乎,必定是我作得太差,那就得好好改这个项目,增长功能。html

新增的下载简历效果图:前端

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

规范化

在开始动工以前,须要考虑本身作什么了,没有接触大公司的规范的开发流程,那也得本身编一个出来。vue

若是有了解如何进行规范化开发的,但愿可以在下方评论处给予我一些参考连接

建立 Issue

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

修改看板

将全部的需求添加至 To do,再将要当即处理的移至 In progressgit

建立分支

准备采用 Github Flow 的工做流,首先建立一个分支,在克隆到本地github

git branch -av
# 建立本地分支并创建关联
git checkout -b feature/download_pdf origin/feature/download_pdf

功能开发

安装依赖

选取的是想法1,利用 canvas 来实现,安装相关的依赖npm

npm i html2canvas -S
npm i jspdf -S

注册功能

这个功能将会被注册为全局的插件进行调用,按照习惯,将其放入 plugins 文件夹下,引入依赖,注册一套走起:canvas

// 建立插件 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

仅能算做勉强完成,分割时会致使连续的内容分开,这个感受会耗时好久……

参考文档

  1. html2canvas
  2. jspdf
  3. toDataURL
相关文章
相关标签/搜索