Статьи

Создание PDF-файлов из веб-страниц на лету с помощью jsPDF

Распечатать PDF с веб-страницы

Формат Portable Document Format является одним из главных нововведений в области настольных издательских систем и автоматизации делопроизводства.

Он также широко используется в веб-публикациях, но, к сожалению, очень часто неправильным образом — как, например, использование его для замены содержимого, которое должно было быть построено на HTML. Это вызывает много проблем, касающихся юзабилити, доступности, SEO и так далее.

Однако в некоторых случаях требуются файлы PDF: когда документ необходимо архивировать и использовать за пределами сети (например, счет-фактура) или когда вам необходим глубокий контроль над печатью.

Именно необходимость контролировать печать привела меня к поиску способа создания PDF-файла.

Цель этой статьи — не просто объяснить, как можно создать PDF (есть много простых способов сделать это), но также сосредоточиться на обстоятельствах, когда файл PDF может решить проблему , и на том, как простой инструмент, такой как jsPDF могу помочь с этим.

Работа с печатью

Любой, кто имел дело с правилами печати CSS, знает, как трудно добиться достойного уровня кроссбраузерной совместимости (посмотрите, например, на таблицу поддержки разрыва страницы в «Можно ли использовать»). Поэтому, когда мне нужно создать что-то, что должно быть напечатано, я всегда стараюсь избегать CSS, и самое простое решение — использовать PDF.

Я не говорю здесь о простом преобразовании HTML в PDF. (Я попробовал несколько инструментов такого типа, но ни один из них не удовлетворил меня полностью.) Моя цель — полностью контролировать расположение и размер элементов, разрывы страниц и так далее.

В прошлом я часто использовал FPDF , инструмент PHP, который может легко предоставить вам такие элементы управления и который может быть легко расширен с помощью многих плагинов .

К сожалению, библиотека, похоже, заброшена (ее последняя версия датируется 2011 годом) (обновление: фактически, последняя версия, по-видимому, относится к декабрю 2015 года ), но благодаря некоторым библиотекам JavaScript у нас теперь есть возможность напрямую создавать файлы PDF. у клиентов (тем самым ускоряя их генерацию).

Когда я начал свой проект, несколько месяцев назад я искал библиотеку JS и, наконец, нашел двух кандидатов: jsPDF и pdfmake . Кажется, pdfmake хорошо документирован и очень прост в использовании, но, поскольку это была бета-версия, я решил использовать jsPDF.

PDF Сборка с помощью jsPDF

Документация jsPDF довольно минимальна, состоит из одной страницы вместе с некоторыми демонстрациями и немного больше информации в исходном файле (или на его страницах jsDoc ), поэтому имейте в виду, что использование его для сложных проектов может быть немного сложным в начало.

В любом случае, jsPDF очень прост для создания базовых файлов PDF. Взгляните на простой пример «Hello World»:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Hello world</title> </head> <body> <h1>Hello world</h1> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.0.272/jspdf.debug.js"></script> <script type="text/javascript"> var pdf = new jsPDF(); pdf.text(30, 30, 'Hello world!'); pdf.save('hello_world.pdf'); </script> </body> </html> 

Эта HTML-страница генерирует одностраничный PDF-файл и сохраняет его на вашем компьютере. Сначала необходимо связаться с библиотекой jsPDF (в данном случае с cdnjs.com ), затем создается экземпляр jsPDF, добавляется строка текста и результат сохраняется как hello_world.pdf .

Обратите внимание, что я использовал версию 1.0.272, и она не самая последняя: на момент написания этой статьи самой последней версией была версия 1.1.135, но у нее много проблем, поэтому я все еще использую предыдущую. ,

Вы можете увидеть, насколько просто создать базовый файл PDF (вы можете найти больше примеров на сайте jsPDF).

Давайте попробуем построить что-то сложнее.

Flyer Project

Несколько месяцев назад меня попросили создать приложение для создания простых листовок. Это было частью более крупного проекта, который имел дело с некоторыми услугами для туристических агентств, и настоящая информация была частично заполнена некоторыми данными JSON.

Основная цель флаера состояла в том, чтобы предоставить простой способ показа специальных предложений, которые будут выставлены в витрине туристического агентства.

Я переставил это приложение для этой статьи, удалив все функциональные возможности на стороне сервера, упростив дизайн флаера, избавившись от совместимости с устаревшими браузерами и создав очень простой интерфейс с Bootstrap 3 и jQuery.

Демонстрация хорошо работает с Firefox и Chrome, в то время как Explorer (или Edge) не позволяет отображать предварительный просмотр, но только для загрузки созданного PDF.

Это пример PDF, созданного с помощью приложения (фото предоставлено Rafael Leão / Unsplash )

Флаер

Функциональная демонстрация доступна в конце этой статьи или непосредственно в CodePen . Обратите внимание, что, поскольку CodePen загружает страницу результатов в iframe, предварительный просмотр PDF — который также загружается в iframe — имеет некоторые проблемы с Chrome и Safari, которые препятствуют отображению предварительного просмотра. (Используйте Firefox, если можете, или попробуйте демо на моем личном сайте ).

Flyer Builder

Пользовательский интерфейс позволяет пользователю вводить некоторые основные данные (заголовок, реферат и цену). При желании можно добавить изображение, в противном случае отображается заголовок Специального предложения в серой рамке.

Другие данные (название агентства, URL-адрес его веб-сайта и логотип) включены в код приложения.

Пользовательский интерфейс

PDF можно предварительно просмотреть в iframe (кроме Explorer или Edge) или загрузить напрямую.

При нажатии кнопки «Просмотр предварительного просмотра» или « Загрузка» файл PDF генерируется с использованием jsPDF и передается в iframe в виде строки URI данных или сохраняется на диск, как в примере выше.

Генерация PDF сначала создает новый экземпляр объекта jsPDF со следующими параметрами: книжная ориентация ( p ), миллиметровые единицы ( mm ), формат «A4».

 var pdf = new jsPDF('p', 'mm', 'a4'); 

Изображения добавляются с addImage функции addImage . Обратите внимание, что каждый объект, размещенный на странице PDF, должен быть точно расположен. Вы должны заботиться о координатах каждого объекта, используя объявленные единицы измерения.

 // pdf.addImage(base64_source, image format, X, Y, width, height) pdf.addImage(agency_logo.src, 'PNG', logo_sizes.centered_x, _y, logo_sizes.w, logo_sizes.h); 

Изображения должны быть в кодировке Base64: логотип агентства встраивается в сценарий в этом формате, а загруженное пользователем изображение кодируется с использованием метода readAsDataURL в readAsDataURL $('#flyer-image').change .

Заголовок добавляется с textAlign функции textAlign . Обратите внимание, что эта функция не является частью ядра jsPDF, но, как было предложено автором в его примерах, библиотека может быть легко расширена с помощью ее API . Вы можете найти textAlign() в верхней части скрипта флаера:

 pdf.textAlign(flyer_title, {align: "center"}, 0, _y); 

Эта функция вычисляет координату X текстовой строки, чтобы сделать ее центрированной, а затем вызывает собственный метод text() :

 pdf.text(text string, X, Y); 

Чтобы изменить свойства текста, вы можете использовать setFontSize() , setFont() , setTextColor() и setFontType() .

Например, чтобы установить красную строку размером 20pt Times Bold, вам нужно набрать:

 pdf.setFontSize(20); pdf.setFont("times"); pdf.setFontType("bold"); pdf.setTextColor(255, 0, 0); pdf.text(10,10, 'This is a 20pt Times Bold red string'); 

В сером поле Специального предложения и ценовом круге используются два аналогичных метода: roundedRect() и circle() . Для обоих из них требуются верхние левые координаты, значения размеров (ширина и высота в первом случае и радиус во втором):

 pdf.roundedRect( X, Y, width, height, radius along X axis, radius along Y axis, style); pdf.circle( X, Y, radius, style); 

Параметры style относятся к свойствам заполнения и обводки объекта. Допустимые стили: S [по умолчанию] для обводки, F для заливки и DF (или FD ) для заливки и обводки.

Свойства заливки и обводки должны быть установлены заранее, используя setFillColor и setDrawColor , для которых требуется значение RGB, и setDrawColor , для которого требуется значение ширины линии в единицах измерения, объявленных в начале документа PDF.

Полный код доступен в демоверсии CodePen:

Вывод

Этот базовый пример показывает, как можно создать очень простой флаер с jsPDF.

Его использование может быть простым, но отсутствие полной документации усложняет каждый шаг.

Я все еще ищу другие решения, следя за другими, такими как pdfmake. Но в конечном счете, я думаю, что единственным действительно окончательным решением может быть лучшая поддержка браузером для печати правил CSS!

Вы использовали jsPDF или что-то подобное? Каким был ваш опыт? Дай мне знать в комментариях.