用PHP的imagettftext繪製文字的換行問題

原文鏈接:https://www.jianshu.com/p/f339fc8d006c

項目的一些說明:

  • 我們在做一個漢字的項目,在這個項目中我們需要使用ps不停的製作一種圖片;
  • 而圖片樣式基本固定。每次製作都需要設計人員重複排版,不停調整圖片和文字間隔和大小;
  • 這樣的事如果做一兩次還是可以忍受的,可是每天都爲這個花費大量的時間,就太折磨人了;
  • 精通php的老闆一看,覺得這個用php就可以解決,於是他就把這活交給了我,通過php自動生成一張樣式統一的卡片,用來減輕設計小女孩的工作量,把她從不停的排版中解除出來(可是我一點不懂php啊,我是做Android的,沒關係,不會我們可以學習嘛。哈哈~~);
  • 就這樣這個任務落到了公司除老闆意外唯一懂技術的我的肩膀上了;
  • 來讓我們看看是什麼樣樣子的一個卡片呢?

項目製作的卡片如下圖:

[圖片上傳失敗...(image-a2974c-1511782668998)]

由圖可以看出,整個大圖由小的圖片和文字組成。由於文字的多少是不確定的,每次的解釋長短不一樣,所以我們用程序畫圖的時候,要動態的根據文字的長短,個數,計算出文字佔用的高度。

我們使用imagettftext這個函數把文字繪製在圖片上,可是問來了,我們要解決換行問題,還要解決行間距的問題。如果我們單純的插入\n作爲換行符,會發現,行間距幾乎爲零,很難看。

下面是自己寫了一個換行算法,並且可以設置行高同時,可以返回文字佔用的高度。也想辦法拍出來,標點符號出現在句首的問題。

下面附上“自動換行”和“計算段落高”的算法,執行後悔直接繪製。:

//下面函數方法我是這樣調用的,這裏是用來測量高度的。

    
     $temp = array("color" => array(99, 99, 99), "fontsize" =>27, "width" => 496, "left" => 100, "top" => 0, "hang_size" => 40);
    //這裏我只用它做測量高度,把參數false改爲true就是繪製了。
    $str_h=draw_txt_to($im, $temp, $str, false);
    

//----------分割線------------

/**
 * 文字自動換行算法
 * @param $card 畫板
 * @param $pos 數組,top距離畫板頂端的距離,fontsize文字的大小,width寬度,left距離左邊的距離,hang_size行高
 * @param $str 要寫的字符串
 * @param $iswrite  是否輸出,ture,  花出文字,false只計算佔用的高度
 * @return int 返回整個字符所佔用的高度
 */

function draw_txt_to($card, $pos, $str, $iswrite)
{

    $_str_h = $pos["top"];
    $fontsize = $pos["fontsize"];
    $width = $pos["width"];
    $margin_lift = $pos["left"];
    $hang_size = $pos["hang_size"];
    $temp_string = "";
    $font_file = "./Fonts/華文細黑.ttf";
    $tp = 0;

    $font_color = imagecolorallocate($card, $pos["color"][0], $pos["color"][1], $pos["color"][2]);
    for ($i = 0; $i < mb_strlen($str); $i++) {

        $box = imagettfbbox($fontsize, 0, $font_file, $temp_string);
        $_string_length = $box[2] - $box[0];
        $temptext = mb_substr($str, $i, 1);

        $temp = imagettfbbox($fontsize, 0, $font_file, $temptext);

        if ($_string_length + $temp[2] - $temp[0] < $width) {//長度不夠,字數不夠,需要

            //繼續拼接字符串。

            $temp_string .= mb_substr($str, $i, 1);

            if ($i == mb_strlen($str) - 1) {//是不是最後半行。不滿一行的情況
                $_str_h += $hang_size;//計算整個文字換行後的高度。
                $tp++;//行數
                if ($iswrite) {//是否需要寫入,核心繪製函數
                    imagettftext($card, $fontsize, 0, $margin_lift, $_str_h, $font_color, $font_file, $temp_string);
                }

            }
        } else {//一行的字數夠了,長度夠了。

//            打印輸出,對字符串零時字符串置null
            $texts = mb_substr($str, $i, 1);//零時行的開頭第一個字。

//            判斷默認第一個字符是不是符號;
            $isfuhao = preg_match("/[\\\\pP]/u", $texts) ? true : false;//一行的開頭這個字符,是不是標點符號
            if ($isfuhao) {//如果是標點符號,則添加在第一行的結尾
                $temp_string .= $texts;

//                判斷如果是連續兩個字符出現,並且兩個丟失必須放在句末尾的,單獨處理
                $f = mb_substr($str, $i + 1, 1);
                $fh = preg_match("/[\\\\pP]/u", $f) ? true : false;
                if ($fh) {
                    $temp_string .= $f;
                    $i++;
                }

            } else {
                $i--;
            }

            $tmp_str_len = mb_strlen($temp_string);
            $s = mb_substr($temp_string, $tmp_str_len-1, 1);//取零時字符串最後一位字符

                if (is_firstfuhao($s)) {//判斷零時字符串的最後一個字符是不是可以放在見面
                    //講最後一個字符用“_”代替。指針前移動一位。重新取被替換的字符。
                    $temp_string=rtrim($temp_string,$s);
                    $i--;
                }
//            }

//            計算行高,和行數。
            $_str_h += $hang_size;
            $tp++;
            if ($iswrite) {

                imagettftext($card, $fontsize, 0, $margin_lift, $_str_h, $font_color, $font_file, $temp_string);
            }
//           寫完了改行,置null該行的臨時字符串。
            $temp_string = "";
        }
    }

    return $tp * $hang_size;

}


function is_firstfuhao($str)
{
    $fuhaos = array("\\"", "“", "'", "<", "《",);

    return in_array($str, $fuhaos);

}

這樣我們的漢字換行繪製輸出,和測量高度的問題就解決了。雖然算法不完美,可是時間有限的情況下,基本能滿足了我們的需求。

Github地址:https://github.com/SaudM/PhpCard

侵權聯繫刪除

作者:小追兵
鏈接:https://www.jianshu.com/p/f339fc8d006c
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章