内容简介:用PHP的imagettftext绘制文字的换行问题
小追兵专栏
项目的一些说明:
-
我们在做一个汉字的项目,在这个项目中我们需要使用ps不停的制作一种图片;
-
而图片样式基本固定。每次制作都需要设计人员重复排版,不停调整图片和文字间隔和大小;
-
这样的事如果做一两次还是可以忍受的,可是每天都为这个花费大量的时间,就太折磨人了;
-
精通 PHP 的老板一看,觉得这个用PHP就可以解决,于是他就把这活交给了我,通过PHP自动生成一张样式统一的卡片,用来减轻设计小女孩的工作量,把她从不停的排版中解除出来(可是我一点不懂PHP啊,我是做Android的,没关系,不会我们可以学习嘛。哈哈~~);
-
就这样这个任务落到了公司除老板意外唯一懂技术的我的肩膀上了;
-
来让我们看看是什么样样子的一个卡片呢?
项目制作的卡片如下图:
乐萌汉字卡片
由图可以看出,整个大图由小的图片和文字组成。由于文字的多少是不确定的,每次的解释长短不一样,所以我们用程序画图的时候,要动态的根据文字的长短,个数,计算出文字占用的高度。
我们使用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); }
这样我们的汉字换行绘制输出,和测量高度的问题就解决了。虽然算法不完美,可是时间有限的情况下,基本能满足了我们的需求。
下篇,我们将实现该图片的图片和卡片的圆角处理。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First HTML and CSS
Elisabeth Robson、Eric Freeman / O'Reilly Media / 2012-9-8 / USD 39.99
Tired of reading HTML books that only make sense after you're an expert? Then it's about time you picked up Head First HTML and really learned HTML. You want to learn HTML so you can finally create th......一起来看看 《Head First HTML and CSS》 这本书的介绍吧!