Схема реализации front-end генерации PDF-файлов

JavaScript

1. Технический отбор

1. После преобразования html в холст сгенерируйте изображения и экспортируйте pdf (выбрано в этой статье)

  • Плагин HTML для холста:html2canvasПлагин, преобразующий HTML-код в Canvas;
  • Холст генерирует PDF:jsPDFэто библиотека с открытым исходным кодом для создания PDF с использованием языка Javascript

2. HTML-код в pdf

wkhtmltopdfЭто плагин, который конвертирует HTML-код в pdf, большинство из которых используется в сценах таблиц.

Во-вторых, реализация технологии (на основе HTML2CANVAS и реализации JSPDF)

1. Установите плагин

npm i html2canvas -S
npm i jspdf -S

2. Регистрация и реализация инкапсуляции

Следующий инкапсулированный код может быть напрямую связан с файлом проекта для использования.Следующие моменты должны быть отмечены:

  1. Поскольку размер экспортируемого pdf-изображения должен быть фиксированным, необходимо добавить класс стиля .pdf-screen в экспортируемый dom, чтобы найти экспортируемый элемент, а затем изменить стиль экспортируемого элемента;
  2. Размер страницы экспорта фиксируется на размере a4;
/**
 * @file 导出pdf文件
 */
import html2canvas from 'html2canvas';
import JsPDF from 'jspdf';

/* eslint-disable */

const PDF = {};

// a4
let a4Width = 595.28; 
let a4Height = 841.89;

let defaultOptions = {
    name: new Date().getTime(),
    scale: window.devicePixelRatio * 2,
    padding: 0,
    width: 595.28 * 2,
    allowTaint: true,
    onclone: function (dom) {
        let screen = dom.querySelector('.pdf-screen');
        screen.style.width = 595.28 * 2 + 'px';
        screen.style.padding = '10px';
    }
}

PDF.install = function (Vue, rootOptions = {}) {
    Vue.prototype.$pdf = function (dom, options = rootOptions) {
        
        options = Object.assign(defaultOptions, options);
        
        html2canvas(dom, options).then(canvas => {
            let position = 0;

            // 生成的画布元素宽高(需要收缩回原比例大小)
            let canvasWidth = canvas.width / options.scale;
            let canvasHeight = canvas.height / options.scale;

            // 页面等比例缩放后宽高
            let pageWidth = a4Width;
            let pageHeight = (a4Width / canvasWidth) * canvasHeight;
            
            //返回图片dataURL,参数:图片格式和清晰度(0-1)
            let jpeg = canvas.toDataURL('image/jpeg', 1.0);

            //方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
            let doc = new JsPDF('', 'pt', 'a4');
            
            //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
            //当内容未超过pdf一页显示的范围,无需分页
            if (canvasHeight < pageHeight) {
                doc.addImage(jpeg, 'JPEG', 0, 0, pageWidth, pageHeight); // 从图片顶部开始打印
            } else {
                while (canvasHeight > 0) {
                    doc.addImage(jpeg, 'JPEG', 0, position, pageWidth, pageHeight);
                    canvasHeight -= pageHeight;
                    position -= a4Height;

                    //避免添加空白页
                    if (canvasHeight > 0) {
                        doc.addPage();
                    }
                }
            }
            doc.save(options.name + '.pdf');
        });
    };
};

export default PDF;

3. Как использовать

// 在 main.js 中导入插件
import pdf from "./plugins/pdf";

// 注册插件
Vue.use(PDF);

// 在需要导出pdf的函数中调用
// dom是需要导出的最外层元素
this.$pdf(dom, options);

// 使用案例(该配置可参考HTML2CANVAS相关配置)
this.$pdf(this.$refs.screen, {
    name: 'filename',   // 导出文件名
    scale: 2,   // 导出文件清晰度,值越大清晰度越高,文件体积越大(默认值为设备dpr*2)
    ignoreElements: (element) => {  // 忽略渲染元素(通过查询dom元素,不局限于类名查询)
        if (element.className.indexOf('className') !== -1) {
            return true;
        }
    }
});

В-третьих, возникшие проблемы и пути их решения.

1. Проблема усечения содержимого PDF (будет решена)

Описание проблемы: Поскольку принцип реализации заключается в преобразовании html в канвас и последующей генерации картинки для экспорта в pdf-файл, содержимое длинного изображения, генерируемого канвой, будет обрезано в процессе листания и сохранения;

2. Проблема разрешения файла экспорта PDF (решена)

Описание проблемы: разрешение изображения, генерируемого холстом, слишком низкое;

Решение: элемент DOM можно масштабировать пропорционально, а затем можно сгенерировать изображение и экспортировать его в файл pdf;

4. Точки для оптимизации

1. Побочный эффект экспорта водяного знака

5. Ссылки