Евгений Горяев
aka floor12

Создание PHP библиотеки для генерации OpenGraph картинок с заголовком статьи

Обложка для статьи Создание  PHP библиотеки для генерации OpenGraph картинок с заголовком статьи

В последнее время все чаще можно заметить тенденцию к размещению заголовка новости или статьи на изображениях, используемых мета- тег og:image.

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

Вот пример такого изображения, взятого сегодня утром из твиттера:

Пример изображения с текстом

А вот так оно выглядит в социальной сети:

Пример изображения с текстом

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

Итак, список параметров, которые необходимо настраивать у меня получился следующий:

  • фоновое изображение;
  • текст, который накладываем поверх изображения;
  • шрифт (в формате ttf);
  • положение текста на изображении по оси X и Y;
  • размер, цвет шрифта и межстрочный интервал.

Положение текста, размер шрифта и межстрочный интервал я решил задавать в процентах от размера изображения, это позволит размещать текст примерно одинаково на изображениях разного размера - что теоретически может понадобится. Кроме того, по моему замыслу, библиотека должна корректно обрабатывать “висячие” в конце строки предлоги, перенося их на следующую строку, если это возможно.

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

  • в конструктор необходимо передать путь к фоновому изображению, на которое будет накладываться текст;
  • с помощью сеттеров задать необходимые параметры;
  • вызвать метод generate() куда передать путь для сохранения итогового изображения.

Почему изображение необходимо задать в конструкторе класса, а не с помощью сеттеров? Это связано с тем, что для установки цвета шрифта необходимо работать с экземпляром объекта Resource библиотеки GD, то есть изображение уже должно быть прочитано. Либо, необходимо делать дополнительную проверку в сеттере цвета текста на наличие прочитанного изображения, что выглядит несколько более “кастыльно”.

Теоретически, можно было бы все параметры задавать через конструктор класса, но учитывая их кол-во, пришлось бы использовать массив, чтобы не делать огромного количества входных параметров в конструкторе. А парсить потом массив параметров мне на данном этапе показалось оверхедом (хотя есть вероятность, это я добавлю этот способ сразу задать все параметры работы библиотеки - такой вариант будет может быть несколько компактнее и изящнее).

В результате получилось неплохое решение, которое работает примерно так:

use floor12\imagenator\Imagenator;

$imagenator = new Imagenator('/path/to/image.png');     // Инициируем объект, передавая путь к изображению в PNG;
$imagenator
    ->setColor('FF04AB')                    // Цвет текста в HEX;
    ->setFont('/fonts/SomeFont.ttf')        // Путь к шрифту;
    ->setFontSize(3)                        // Размер шрифта в процентах от высото изображения;
    ->setPadding(5)                         // Отсутпы от края картинки в процентах по оси X в процентах от ширины изображения;
    ->setMarginTopInPercents(50)            // Отступ от верхнего края в процентах от высоты изображения;
    ->setRowHeight(7)                       // Высота строк в процентах от высото изображения;
    ->setText('This is an article title.')  // Текст, который необходимо поместить на изображения
    ->generate('/path/to/save.png');        // Сохраняем итоговое изображение в формате PNG

В результате мы можем генерировать изображения приблизительно следующего содержания:

Пример изображения с текстом

Пример изображения с текстом

Пример изображения с текстом

Вы можете найти эту библиотеку в моем GitHub