2

PHP 関数 imagettftext に問題があります。テキスト情報を含むデータベースからカード画像を生成するコードがあります。そして、いくつかのカードでは問題があります-単語が互いに上書きされます(ここのように)。

私のコードは次のようになります(テキストの長さによってフォントサイズが変わります)

            $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」という言葉が次の行にあるのかわかりません。

回答ありがとうございます。

4

3 に答える 3

3

かなり前に、同様のタスクをアーカイブするために非常に複雑なクラスを作成しました。

このコードはもうありませんが、手順はかなり簡単です。

最初に: 計算に頼らないでください。php はまれなフォントを使用します。

Php の wordwrap-function は、ここでは意味がありません。なぜなら、php にとって未知の文字セット幅 (追跡など) を扱うからです。Wordwrap は、すべての文字の文字幅が同じであると想定しています。

そのため、imagettfbbox を使用して独自のワードラップ関数を作成する必要があります。次に、小文字の「x」文字と大文字の「X」文字のサイズを決定する必要があります。これらの文字は、独自の行の高さ/行間隔を計算するための標準です。また、PHP は常に空白の幅を正しく認識できるとは限らないため、単語を手動で区切ることをお勧めします。

これがあなたを助けることを願っています...

于 2012-07-16T10:55:56.517 に答える
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();
于 2012-08-03T21:56:32.187 に答える
0

必要なボックスにそのような見積もりを使用しないでください。

関数 imagettfbbox() は、テキストを表示するために必要なボックスに対する明確な答えを与えることができます。

http://nl3.php.net/manual/en/function.imagettfbbox.php

それが役立つことを願っています。

于 2012-07-16T13:07:23.820 に答える