Время чтения: 4 мин.
Реализация с использованием паттерна Builder позволяет сделать код более структурированным и гибким. Мы создадим класс TextOnImageBuilder
, который будет отвечать за построение изображения с текстом, вписанным в прямоугольник. Этот класс будет использовать шаги для настройки параметров и выполнения задачи.
Реализация с паттерном Builder
1. Класс TextOnImageBuilder
use Intervention\Image\ImageManager;
class TextOnImageBuilder
{
private $manager;
private $image;
private $text;
private $fontPath;
private $textColor = '#000000';
private $rectWidth;
private $rectHeight;
private $rectX = 0;
private $rectY = 0;
private $maxFontSize = 24;
private $lineHeightMultiplier = 1.2;
public function __construct($driver = 'gd')
{
$this->manager = new ImageManager(['driver' => $driver]);
}
public function setImagePath($path)
{
$this->image = $this->manager->make($path);
return $this;
}
public function setText($text)
{
$this->text = $text;
return $this;
}
public function setFontPath($path)
{
$this->fontPath = $path;
return $this;
}
public function setTextColor($color)
{
$this->textColor = $color;
return $this;
}
public function setRectangle($width, $height, $x = 0, $y = 0)
{
$this->rectWidth = $width;
$this->rectHeight = $height;
$this->rectX = $x;
$this->rectY = $y;
return $this;
}
public function setMaxFontSize($size)
{
$this->maxFontSize = $size;
return $this;
}
public function setLineHeightMultiplier($multiplier)
{
$this->lineHeightMultiplier = $multiplier;
return $this;
}
private function getTextWidth($text, $fontSize)
{
$box = imagettfbbox($fontSize, 0, $this->fontPath, $text);
return abs($box[2] - $box[0]);
}
private function getTextHeight($text, $fontSize)
{
$box = imagettfbbox($fontSize, 0, $this->fontPath, $text);
return abs($box[7] - $box[1]);
}
private function calculateOptimalFontSize()
{
$fontSize = $this->maxFontSize;
while ($fontSize > 0) {
$lines = explode("\n", wordwrap($this->text, 20, "\n"));
$totalHeight = 0;
foreach ($lines as $line) {
$totalHeight += $this->getTextHeight($line, $fontSize) * $this->lineHeightMultiplier;
}
if ($totalHeight <= $this->rectHeight) {
$fits = true;
foreach ($lines as $line) {
if ($this->getTextWidth($line, $fontSize) > $this->rectWidth) {
$fits = false;
break;
}
}
if ($fits) {
return $fontSize;
}
}
$fontSize--;
}
throw new \Exception('Текст не помещается в прямоугольник');
}
public function applyText()
{
if (!$this->image || !$this->text || !$this->fontPath) {
throw new \Exception('Необходимо указать изображение, текст и шрифт');
}
$fontSize = $this->calculateOptimalFontSize();
$lines = explode("\n", wordwrap($this->text, 20, "\n"));
$y = $this->rectY + ($this->rectHeight - $this->getTextHeight($this->text, $fontSize) * $this->lineHeightMultiplier * count($lines)) / 2;
foreach ($lines as $line) {
$lineHeight = $this->getTextHeight($line, $fontSize) * $this->lineHeightMultiplier;
$this->image->text($line, $this->rectX + $this->rectWidth / 2, $y, function ($font) use ($fontSize) {
$font->file($this->fontPath);
$font->size($fontSize);
$font->color($this->textColor);
$font->align('center');
$font->valign('top');
});
$y += $lineHeight;
}
return $this;
}
public function save($path)
{
$this->image->save($path);
return $this;
}
public function output()
{
header('Content-Type: image/jpeg');
echo $this->image->encode('jpg');
}
}
2. Использование Builder
Теперь мы можем использовать TextOnImageBuilder
для добавления текста на изображение:
$builder = new TextOnImageBuilder('gd'); // Используем драйвер GD
try {
$builder
->setImagePath('path/to/your/image.jpg') // Путь к изображению
->setText('Это текст, который нужно вписать в прямоугольник') // Текст
->setFontPath('path/to/your/font.ttf') // Путь к шрифту
->setTextColor('#ffffff') // Цвет текста
->setRectangle(300, 100, 50, 50) // Прямоугольник (ширина, высота, x, y)
->setMaxFontSize(24) // Максимальный размер шрифта
->setLineHeightMultiplier(1.2) // Множитель межстрочного интервала
->applyText() // Применить текст
->save('path/to/save/image.jpg'); // Сохранить изображение
// Или вывести изображение в браузер
// $builder->output();
} catch (\Exception $e) {
echo 'Ошибка: ' . $e->getMessage();
}
Преимущества использования Builder:
- Гибкость: Каждый метод настраивает отдельный параметр, что делает код более читаемым и удобным для использования.
- Расширяемость: Легко добавить новые параметры (например, угол наклона текста или тень).
- Повторное использование: Можно использовать один и тот же Builder для создания нескольких изображений с разными параметрами.
Пример вызова с другими параметрами:
$builder = new TextOnImageBuilder('imagick'); // Используем драйвер Imagick
$builder
->setImagePath('path/to/another/image.jpg')
->setText('Другой текст')
->setFontPath('path/to/another/font.ttf')
->setTextColor('#ff0000')
->setRectangle(400, 150, 100, 100)
->setMaxFontSize(30)
->setLineHeightMultiplier(1.5)
->applyText()
->save('path/to/save/another_image.jpg');
Этот подход делает код более модульным и удобным для работы с изображениями и текстом.
Добавить комментарий