Добавление текста к изображению с помощью PHP и GD
Код
Я добавил комментарии в код для пояснения того, что он делает. В коде используется Laravel хелпер public_path()
, но вместо него можно использовать нативный PHP или другой фреймворк:
// Получение изображения шаблона, к которому необходимо добавить текст
$image = public_path('social/social-template.png');
// Создание объекта GD Image
$image = imagecreatefromstring($image);
// Определение цвета и размера шрифта текста
$navy = imagecolorallocate($image, 20, 45, 111);
$font_size = 128;
$font_path = public_path('fonts/Jokker-Semibold.woff');
// Перенос текста на основе максимальной ширины (см. следующий блок кода)
$text = $this->wrapText('This is my title', $font_size, $font_path);
// Добавление текста к изображению
imagettftext(
image: $image,
size: $font_size,
angle: 0,
x: 210,
y: 550,
color: $navy,
font_filename: $font_path,
text: trim($text)
);
// Сохранение изображения
imagepng($image, public_path("social/images/this-is-my-title.png"));
// Очистка памяти
imagedestroy($image);
Перенос текста
Определить максимальную ширину и перенести текст не так просто, поскольку для каждого шрифта будет разная ширина текста. К счастью, GD предоставляет методы для расчёта этой ширины:
public function wrapText(string $text, int $font_size, string $font_path): string
{
// Переменная для хранения результата
$wrapped = '';
// Делим текст на массив слов
$words = explode(' ', $text);
foreach ($words as $word) {
// Вычисляем размер текущего результата + дополнительное слово
$teststring = "{$wrapped} {$word}";
$testbox = imagettfbbox($font_size, 0, $font_path, $teststring);
// Если ширина тестового блока превышает максимально допустимую ширину,
// добавляем разрыв строки перед словом, в противном случае добавляем пробел
if ($testbox[2] > 1900) {
$wrapped .= "\n".$word;
} else {
$wrapped .= ' '.$word;
}
}
return $wrapped;
}
Альтернативы
Если вы предпочитаете работать с HTML и CSS для генерации изображений, обратите внимание на spatie/browsershot.
Пакет может конвертировать веб-страницу в изображение или pdf. Преобразование происходит за сценой с помощью Puppeteer, управляющего headless версией Google Chrome.
use Spatie\Browsershot\Browsershot;
// будет сохранено изображение
Browsershot::url('https://example.com')->save($pathToImage);
Будет сохранён pdf, если путь, переданный в метод save
, имеет расширение pdf.
// будет сохранён pdf
Browsershot::url('https://example.com')->save('example.pdf');
Вы также можете использовать произвольный html код, просто заменив метод url
на html
:
Browsershot::html('<h1>Hello world!!</h1>')->save('example.pdf');
Если HTML код уже сохранён в локальном файле, используйте:
Browsershot::htmlFromFilePath('/local/path/to/file.html')->save('example.pdf');