Формат 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 или что-то подобное? Каким был ваш опыт? Дай мне знать в комментариях.