我的PHP函数imagettftext有问题。我有用于从数据库生成带有文本信息的卡片图像的代码。有些卡我有问题 - 单词互相写(like here)。
我的代码看起来像这样(字体大小会根据文本的长度而变化)
$length = strlen($cardInfo->description);
if ($length < 15) {
$divide = 15;
$fontSize = 16;
$lineHeight = 25;
$startPos = 220;
} else if ($length < 70) {
$divide = 25;
$fontSize = 12;
$lineHeight = 18;
$startPos = 210;
} else if ($length < 110) {
$divide = 28;
$fontSize = 10;
$lineHeight = 14;
$startPos = 210;
} else {
$divide = 38;
$fontSize = 8;
$lineHeight = 13;
$startPos = 210;
}
$description = wordwrap($cardInfo->description, $divide, ">>>");
$lines = explode(">>>", $description);
$count = 0;
foreach ($lines as $line) {
$position = $count * $lineHeight;
$count++;
imagettftext($image, $fontSize, 0, 28, ($startPos + $position), $black, $font, $line);
}
,数据库中的文字如下所示:
Oblehací stroj
Imunita vůči střelám /Tato jednotka je imunní vůči střeleckým zraněním/
其他问题在于换行:here。我不知道为什么“jídlo”这个词出现在下一行。
感谢您的回答!
答案 0 :(得分:3)
很久以前,我写了一个非常复杂的类来存档类似的任务。
我没有这个代码,但步骤相当简单。
第一:不要依赖计算,php会对稀有字体进行计算。
Php的wordwrap-function在这里毫无意义,因为你处理了php未知的charset-width(例如跟踪)。 Wordwrap假设所有字符都具有相同的字符宽度。
因此,您必须使用imagettfbbox构建自己的wordwrap函数。然后,您将必须确定小写“x”字母和大写“X”字母的大小。这些字母是计算您自己的行高/行间距的标准。我还建议您手动分隔单词,因为PHP并不总能正确识别空白宽度。
希望这可以帮助你...
答案 1 :(得分:1)
这对我有用。您需要arial.ttf
和http://dark-project.cz/CardDatabase/cards/lehky_katapult.png
。
class Test_Canvas {
protected $res=null;
public function __construct($width, $height) {
$this->res = imagecreatetruecolor($width, $height);
imagealphablending($this->res, true);
imagesavealpha($this->res, true);
imagefill($this->res, 0, 0, imagecolorallocatealpha($this->res, 0, 0, 0, 127));
}
public function copyTo(Test_Canvas $canvas, $x, $y) {
imagecopyresampled($canvas->res, $this->res, $x, $y, 0, 0, $this->getWidth(), $this->getHeight(), $this->getWidth(), $this->getHeight());
}
public function getWidth() {
return imagesx($this->res);
}
public function getHeight() {
return imagesy($this->res);
}
public function saveAsPNG() {
imagepng($this->res);
}
}
class Test_Canvas_Image_PNG extends Test_Canvas {
public function __construct($filename) {
$res = imagecreatefrompng($filename);
$w = imagesx($res);
$h = imagesy($res);
parent::__construct($w, $h);
imagecopymerge($this->res, $res, 0, 0, 0, 0, $w, $h, 100);
}
}
class Test_Canvas_Textarea extends Test_Canvas {
private $text;
private $fontsize;
private $fontfile;
public function __construct($width, $height, $text, $fontsize, $fontfile) {
parent::__construct($width, $height);
$this->text = $text;
$this->fontsize = $fontsize;
$this->fontfile = $fontfile;
$this->removeDuplicateWhitespace();
$this->formatText();
$this->applyText();
}
private function removeDuplicateWhitespace() {
$this->text = preg_replace('/[ \t]+/', ' ', $this->text);
}
private function formatText() {
$lines = explode("\n", $this->text);
$res = array();
foreach ($lines as $line) {
$res[] = $this->insertAdditionalLinebreaks($line);
}
$this->text = join("\n", $res);
}
private function insertAdditionalLinebreaks($line) {
$words = $this->splitWords($line);
$res = array();
$line = "";
while(count($words)) {
$word = array_shift($words);
$testLine = "{$line} {$word}";
$width = $this->getTextWidth($testLine);
if($width > $this->getWidth()) {
$res[] = $line;
$line = $word;
} elseif(!count($words)) {
$res[] = $testLine;
} else {
$line = $testLine;
}
}
return join("\n", $res);
}
private function getTextWidth($text) {
$boundaries = imagettfbbox($this->fontsize, 0, $this->fontfile, $text);
$x1 = min($boundaries[0], $boundaries[6]);
$x2 = max($boundaries[2], $boundaries[4]);
return $x2 - $x1;
}
private function splitWords($text) {
return explode(' ', $text);
}
private function applyText() {
$lines = explode("\n", $this->text);
foreach($lines as $lineNo => $line) {
imagettftext($this->res, $this->fontsize, 0, 0, ($lineNo + 1) * ($this->fontsize + 5), imagecolorallocate($this->res, 0, 0, 0), $this->fontfile, $line);
}
}
}
$rootPath = dirname(__FILE__).'/';
$imageFilename = "{$rootPath}test.png";
$description = "Oblehací stroj\nImunita vuci strelám /Tato jednotka je imunní vuci streleckým zranením/ ";
$description .= $description;
$description .= $description;
header('Content-Type: image/png');
$canvas = new Test_Canvas_Image_PNG($imageFilename);
$text = new Test_Canvas_Textarea(179, 92, $description, 9, 'arial.ttf');
$text->copyTo($canvas, 25, 193);
$canvas->saveAsPNG();
答案 2 :(得分:0)
您不应该对您需要的方框使用此类估算值。
函数imagettfbbox()可以为您提供显示文本所需的框的明确答案。
http://nl3.php.net/manual/en/function.imagettfbbox.php
希望有所帮助。