Closed tpavlek closed 7 months ago
It's not possible at the moment, but would be useful indeed.
+1
+1. any updates on this? Or has anyone found any interesting methods to mimic it?
+1 when it will added to the next version?
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
here's what I did for the meantime:
Inside my Laravel controller:
<?php
$width = 600;
$height = 300;
$center_x = $width / 2;
$center_y = $height / 2;
$max_len = 36;
$font_size = 30;
$font_height = 20;
$text = 'The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog?';
$lines = explode("\n", wordwrap($text, $max_len)
$y = $center_y - ((count($lines) - 1) * $font_height);
$img = \Image::canvas($width, $height, '#777');
foreach ($lines as $line)
{
$img->text($line, $center_x, $y, function($font) use ($font_size){
$font->file(base_path('path/to/my/font.ttf'));
$font->size($font_size);
$font->color('#fdf6e3');
$font->align('center');
$font->valign('center');
});
$y += $font_height * 2;
}
return $img->response();
+1
+1
+1
+1
+1
+1
+1
+1
+2
function getTextWith($fontSize, $text)
{
$im = new Imagick();
$draw = new ImagickDraw();
$draw->setFont($this->fontPath);
$draw->setFontSize($fontSize);
$info = $im->queryFontMetrics($draw, $text);
return $info['textWidth'];
}
get height by $info['textHeight']
Had this issue this morning, so wrote a function to help with this:
/**
* Generate an array of "lines" our text should
* use
*
* @param String $text
* @param Number $width
* @param Number $size (Font size)
* @param String $font (Font path)
* @return Array [text]
*/
public function generateText($text, $width, $size, $path)
{
//-- Helpers
$line = [];
$lines = [];
//-- Looop through words
foreach(explode(" ", $text) AS $word)
{
//-- Add to line
$line[] = $word;
//-- Create new text query
$im = new \Imagick();
$draw = new \ImagickDraw();
$draw->setFont($path);
$draw->setFontSize($size);
$info = $im->queryFontMetrics($draw, implode(" ", $line));
//-- Check within bounds
if ($info['textWidth'] >= $width)
{
//-- We have gone to far!
array_pop($line);
$lines[] = implode(" ", $line);
//-- Start new line
unset($line);
$line[] = $word;
}
}
//-- We are at the end of the string
$lines[] = implode(" ", $line);
return $lines;
}
I then use this by doing the following on my image:
$textLines = $this->generateText(
'This is a image that has quite a large name so should overlap',
700,
$fontSize,
$fontPath
);
foreach($textLines AS $index => $text)
{
$y = (($index * $fontSize) + $padding);
$image->text($text, $padding, $y, function($font) use ($fontPath, $fontSize) {
$font->file($fontPath);
$font->size($fontSize);
$font->color('#fdf6e3');
$font->align('left');
$font->valign('top');
});
}
+1
Seriously this issue is opened from 6 years and it hasn't been fixed?!
+1
Need this specific feature too now :)
+1 please
Just to provide another alternative:
$canvas = Image::canvas(1080, 1080);
$canvas->fill('#FFFFFF');
$this->text = wordwrap('your text here', 40, PHP_EOL);
$canvas->text($this->text, 100, 100, function($font) {
$font->size(50);
$font->color('#000000');
// you can log $font->countLines() to see how many lines you have
});
+1
here's what I did for the meantime:
Inside my Laravel controller:
<?php $width = 600; $height = 300; $center_x = $width / 2; $center_y = $height / 2; $max_len = 36; $font_size = 30; $font_height = 20; $text = 'The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog?'; $lines = explode("\n", wordwrap($text, $max_len) $y = $center_y - ((count($lines) - 1) * $font_height); $img = \Image::canvas($width, $height, '#777'); foreach ($lines as $line) { $img->text($line, $center_x, $y, function($font) use ($font_size){ $font->file(base_path('path/to/my/font.ttf')); $font->size($font_size); $font->color('#fdf6e3'); $font->align('center'); $font->valign('center'); }); $y += $font_height * 2; } return $img->response();
You made my day with this 👍
+1
Me habéis salvado la vida, estoy trabajando en un desarrollo web y una consultoría SEO y necesitaba generar imágenes para el open graph de forma dinámica, después de muchos intentos aquí he encontrado la solución. Muchas gracias!
Thanks for your code @jakeydevs!
I've improved/optimized it a bit, so you can pass your FontInterface
implementation and Imagick
/ImagickDraw
instances are initialized outside the foreach
:
private static function wrapText(string $text, int $width, FontInterface $font): array
{
$imagick = new \Imagick();
$imagickDraw = new \ImagickDraw();
$imagickDraw->setFont($font->filename());
$imagickDraw->setFontSize($font->size());
$line = [];
$lines = [];
foreach (explode(' ', $text) as $word) {
$line[] = $word;
$fontMetrics = $imagick->queryFontMetrics($imagickDraw, implode(' ', $line));
// If our line doesn't fit, remove the last word and place it on a new line
if ($fontMetrics['textWidth'] >= $width) {
array_pop($line);
$lines[] = implode(' ', $line);
$line = [$word];
}
}
$lines[] = implode(' ', $line);
return $lines;
}
Then you can easily use it like this, it will draw the text by respecting your font size and line-height:
private function drawTitle(ImageManager $imageManager, ImageInterface $interventionImage): void
{
$padding = 56; // If you want some padding at left/right of your image
$font = (new Font($this->projectDir . '/assets/fonts/Inter/static/Inter-Bold.ttf'))
->setSize(56)
->setColor('rgba(255, 255, 255, 0.85)')
->setLineHeight(1.6)
->setValignment('top');
foreach (self::wrapText('Lorem ipsum dolor sit amet ...', $interventionImage->width() - ($padding * 2), $font) as $i => $line) {
$interventionImage
->text(
$line,
$padding,
$padding + $i * $font->size() * $font->lineHeight(),
$font,
);
}
}
Text wrapping is finally part of Intervention Image as of version 3.4
. See #1292
Thank you for waiting almost 10 years. 🙈
Thanks! :)
I have an image and I would like to have a paragraph of text appearing within a certain bounded box on the image. Is there any way with the current implementation to define a bounding box and have the text wrap/resize within it to fit inside?
If not, I think this would be a useful feature to have.
Thanks