小追兵專欄
項(xiàng)目的一些說(shuō)明:
- 我們?cè)谧鲆粋€(gè)漢字的項(xiàng)目废离,在這個(gè)項(xiàng)目中我們需要使用ps不停的制作一種圖片琳拭;
- 而圖片樣式基本固定枣接。每次制作都需要設(shè)計(jì)人員重復(fù)排版盒至,不停調(diào)整圖片和文字間隔和大小争舞;
- 這樣的事如果做一兩次還是可以忍受的凛忿,可是每天都為這個(gè)花費(fèi)大量的時(shí)間,就太折磨人了兑障;
- 精通php的老板一看侄非,覺(jué)得這個(gè)用php就可以解決蕉汪,于是他就把這活交給了我,通過(guò)php自動(dòng)生成一張樣式統(tǒng)一的卡片逞怨,用來(lái)減輕設(shè)計(jì)小女孩的工作量者疤,把她從不停的排版中解除出來(lái)(可是我一點(diǎn)不懂php啊,我是做Android的叠赦,沒(méi)關(guān)系驹马,不會(huì)我們可以學(xué)習(xí)嘛。哈哈~~)除秀;
- 就這樣這個(gè)任務(wù)落到了公司除老板意外唯一懂技術(shù)的我的肩膀上了糯累;
- 來(lái)讓我們看看是什么樣樣子的一個(gè)卡片呢?
項(xiàng)目制作的卡片如下圖:
[圖片上傳失敗...(image-a2974c-1511782668998)]
由圖可以看出册踩,整個(gè)大圖由小的圖片和文字組成泳姐。由于文字的多少是不確定的,每次的解釋長(zhǎng)短不一樣暂吉,所以我們用程序畫圖的時(shí)候胖秒,要?jiǎng)討B(tài)的根據(jù)文字的長(zhǎng)短,個(gè)數(shù)慕的,計(jì)算出文字占用的高度阎肝。
我們使用imagettftext這個(gè)函數(shù)把文字繪制在圖片上,可是問(wèn)來(lái)了肮街,我們要解決換行問(wèn)題风题,還要解決行間距的問(wèn)題。如果我們單純的插入\n作為換行符嫉父,會(huì)發(fā)現(xiàn)沛硅,行間距幾乎為零,很難看熔号。
下面是自己寫了一個(gè)換行算法稽鞭,并且可以設(shè)置行高同時(shí)鸟整,可以返回文字占用的高度引镊。也想辦法拍出來(lái),標(biāo)點(diǎn)符號(hào)出現(xiàn)在句首的問(wèn)題篮条。
下面附上“自動(dòng)換行”和“計(jì)算段落高”的算法弟头,執(zhí)行后悔直接繪制。:
//下面函數(shù)方法我是這樣調(diào)用的涉茧,這里是用來(lái)測(cè)量高度的赴恨。
$temp = array("color" => array(99, 99, 99), "fontsize" =>27, "width" => 496, "left" => 100, "top" => 0, "hang_size" => 40);
//這里我只用它做測(cè)量高度,把參數(shù)false改為true就是繪制了伴栓。
$str_h=draw_txt_to($im, $temp, $str, false);
//----------分割線------------
/**
* 文字自動(dòng)換行算法
* @param $card 畫板
* @param $pos 數(shù)組伦连,top距離畫板頂端的距離雨饺,fontsize文字的大小,width寬度惑淳,left距離左邊的距離额港,hang_size行高
* @param $str 要寫的字符串
* @param $iswrite 是否輸出,ture歧焦, 花出文字移斩,false只計(jì)算占用的高度
* @return int 返回整個(gè)字符所占用的高度
*/
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/華文細(xì)黑.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) {//長(zhǎng)度不夠,字?jǐn)?shù)不夠绢馍,需要
//繼續(xù)拼接字符串向瓷。
$temp_string .= mb_substr($str, $i, 1);
if ($i == mb_strlen($str) - 1) {//是不是最后半行。不滿一行的情況
$_str_h += $hang_size;//計(jì)算整個(gè)文字換行后的高度舰涌。
$tp++;//行數(shù)
if ($iswrite) {//是否需要寫入猖任,核心繪制函數(shù)
imagettftext($card, $fontsize, 0, $margin_lift, $_str_h, $font_color, $font_file, $temp_string);
}
}
} else {//一行的字?jǐn)?shù)夠了,長(zhǎng)度夠了瓷耙。
// 打印輸出超升,對(duì)字符串零時(shí)字符串置null
$texts = mb_substr($str, $i, 1);//零時(shí)行的開頭第一個(gè)字。
// 判斷默認(rèn)第一個(gè)字符是不是符號(hào)哺徊;
$isfuhao = preg_match("/[\\\\pP]/u", $texts) ? true : false;//一行的開頭這個(gè)字符室琢,是不是標(biāo)點(diǎn)符號(hào)
if ($isfuhao) {//如果是標(biāo)點(diǎn)符號(hào),則添加在第一行的結(jié)尾
$temp_string .= $texts;
// 判斷如果是連續(xù)兩個(gè)字符出現(xiàn)落追,并且兩個(gè)丟失必須放在句末尾的盈滴,單獨(dú)處理
$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);//取零時(shí)字符串最后一位字符
if (is_firstfuhao($s)) {//判斷零時(shí)字符串的最后一個(gè)字符是不是可以放在見面
//講最后一個(gè)字符用“_”代替。指針前移動(dòng)一位轿钠。重新取被替換的字符巢钓。
$temp_string=rtrim($temp_string,$s);
$i--;
}
// }
// 計(jì)算行高,和行數(shù)疗垛。
$_str_h += $hang_size;
$tp++;
if ($iswrite) {
imagettftext($card, $fontsize, 0, $margin_lift, $_str_h, $font_color, $font_file, $temp_string);
}
// 寫完了改行症汹,置null該行的臨時(shí)字符串。
$temp_string = "";
}
}
return $tp * $hang_size;
}
function is_firstfuhao($str)
{
$fuhaos = array("\\"", "“", "'", "<", "《",);
return in_array($str, $fuhaos);
}
這樣我們的漢字換行繪制輸出贷腕,和測(cè)量高度的問(wèn)題就解決了背镇。雖然算法不完美,可是時(shí)間有限的情況下泽裳,基本能滿足了我們的需求瞒斩。
Github地址:https://github.com/SaudM/PhpCard
下篇,我們將實(shí)現(xiàn)該圖片的圖片和卡片的圓角處理涮总。
最后:有需要Shadowsock翻墻賬號(hào)可以私聊胸囱。