胖蔡说技术
随便扯扯

Vue 中使用 html2Canvas 实现 html 生成 PDF 文件

前端开发过程中,可能需要将我们预览的数据通过 pdf 的方式下载保存。这时,我们就可以通过 html2canvas+jspdf 结合的方式来实现。通常情况下,jspdf 已经可以完成由 html 转 pdf 的功能了,但 jspdf 并不支持中文环境(开发人员是国外友人),这时候我们就需要先通过 html2Canvas 将 html 内容绘制到 canvas 中,然后通过 canvas 保存为图片,最后通过 jspdf 将图片生成 pdf 文件。

e301e5fe9ee1f08

通过上述的了解,我们可以将整个的封装过程分为如下几个部分:

  1. 通过 html2Canvas,将目标 dom 渲染到 canvas 中

import html2Canvas from "html2canvas";

/**
 * 通过dom的id将其加载到canvas中,并返回canvas的data数据
 * @params id dom的id
 *
 * */
function generateCanvas(id) {
  const elements = document.getElementById(id);
  const canvas = html2Canvas(element, {
    dpi: 172,
    useCORS: true,
    allowTaint: false,
    backgroundColor: "#fff",
    logging: false,
    pagesplit: true,
    scale: 1.5,
  });

  const contentWidth = canvas.width;
  const contentHeight = canvas.height;
  // 页面偏移
  const position = 0;
  // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
  const imgWidth = 595.28;
  const imgHeight = (595.28 / contentWidth) * contentHeight;
  const pageData = canvas.toDataURL("image/jpeg", 1.0);
  return {
    data: pageData,
    height: contentHeight,
    width: contentWidth,
  };
}
  1. 将 html 生成 canvas 后,我们需要将 canvas 通过 jsPdf 加载并以 pdf 的方式导出(下载)

import JsPDF from "jspdf";

function saveAsPdf(filename) {
  const pdf = new JsPDF("", "pt", "a4", true);
  const target = generateCanvas("template");
  const { data, height, width } = target;
  // 一页pdf显示html页面生成的canvas高度;
  const pageHeight = (width / 592.28) * 841.89;
  // 未生成pdf的html页面高度
  let leftHeight = height;

  if (leftHeight < pageHeight) {
    pdf.addImage(pageData, "JPEG", 0, 0, imgWidth, imgHeight);
  } else {
    while (leftHeight > 0) {
      pdf.addImage(pageData, "JPEG", 0, position, imgWidth, imgHeight);
      leftHeight -= pageHeight;
      // 避免添加空白页
      position -= 841.89;
      if (leftHeight > 0) {
        pdf.addPage();
      }
    }
  }
  pdf.save(`${filename}.pdf`);
}
  1. 功能完成后就需要将其和 vue 集成了


// 将导出功能封装成一个vue指令并在全局加载  /src/directive/jsPrintPDF
import html2Canvas from 'html2canvas';
import JsPDF from 'jspdf';


export default {
    inserted:function(el,binding){
        const { value } = binding;
        el.addEventListener('click',()=>{

             const canvas = html2Canvas(element,{
                  dpi: 172,
                  useCORS: true,
                  allowTaint: false,
                  backgroundColor: '#fff',
                  logging: false,
                  pagesplit: true,
                  scale: 1.5,
            });
            const contentWidth = canvas.width;
            const contentHeight = canvas.height;
            // 页面偏移
            const position = 0;
            // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
           const imgWidth = 595.28;
           const imgHeight = 595.28 / contentWidth * contentHeight;
           const pageData = canvas.toDataURL('image/jpeg', 1.0);

           const pdf = new JsPDF("", "pt", "a4", true);
           // 一页pdf显示html页面生成的canvas高度;
           const pageHeight = (contentWidth / 592.28) * 841.89;
           // 未生成pdf的html页面高度
           let leftHeight = contentHeight;

          if (leftHeight < pageHeight) {
            pdf.addImage(pageData, "JPEG", 0, 0, imgWidth, imgHeight);
          } else {
               while (leftHeight > 0) {
                   pdf.addImage(pageData, "JPEG", 0, position, imgWidth, imgHeight);
                   leftHeight -= pageHeight;
                    // 避免添加空白页
                   position -= 841.89;
                   if (leftHeight > 0) {
                      pdf.addPage();
                    }
                }
           }
          pdf.save(`${value||'未命名'}.pdf`);
        })
    }
}



// main.js中加载该指令

import jsPdfDt from '@/directive/jsPrintPDF';
Vue.use({
    install:{
        Vue.directive('loadpdf',jsPdfDt);
    }
})

通过上面的封装后,我们就可以在全局使用v-loadpdf指令了,使用如下:

<div v-loadpdf="测试下载文件">这里是下载区域 </div>
赞(0) 打赏
转载请附上原文出处链接:胖蔡说技术 » Vue 中使用 html2Canvas 实现 html 生成 PDF 文件
分享到: 更多 (0)

请小编喝杯咖啡~

支付宝扫一扫打赏

微信扫一扫打赏