本文可以幫助你解決一下問題:
1咆繁,GD庫添加文字水印無法換行
2讳推,GD庫添加文本實現(xiàn)居中顯示
3,stil/gd-text擴展包添加文字為中文時么介,換行失效
GD庫是php處理圖形的擴展庫娜遵,GD庫提供了一系列用來處理圖片的API,使用GD庫可以處理圖片壤短,或者生成圖片设拟,也可以給圖片加水印。我們常用它生成網(wǎng)址驗證碼久脯,圖片縮略圖纳胧,分享海報等等。
一帘撰,前置條件
1跑慕,確保你的PHP安裝了GD擴展,并在php.ini啟用了該擴展
2摧找,phpinfo()查看GD擴展已開啟:
3核行,以下每段代碼快最后三句均為調(diào)試代碼,用以在瀏覽器查看當(dāng)前圖片蹬耘。所有代碼塊連接在一起時芝雪,需要去除調(diào)試代碼
二,創(chuàng)建一幅圖片(畫布)
//1综苔,添加一個畫布$img惩系,同時給這個畫布添加背景圖片$bg
$bgPath = './images/bg.jpg';
$bgInfo = getimagesize($bgPath);
$bgFun = 'imagecreatefrom'.image_type_to_extension($bgInfo[2], false);
//創(chuàng)建一個圖: 460*830
$bg = $bgFun($bgPath);
$bgWidth = imagesx($bg); //背景寬度
$bgHeight = imagesy($bg); //背景高度
$img = imageCreatetruecolor($bgWidth,$bgHeight);
$color = imagecolorallocate($img, 0, 0, 0);
imagefill($img, 0, 0, $color);
//平滑的拷貝背景圖到$img
imagecopyresampled($img,$bg,0,0,0,0,imagesx($bg),imagesy($bg),imagesx($bg),imagesy($bg));
//打印查看:
header('Content-Type: image/png;charset=UTF-8');//必須聲明
imagepng($img);
exit;
三,為圖片添加水印
//2如筛,使用GD庫在一張圖片上面加文字:
$font = realpath("./font/simhei.ttf");
//顯示的文字
$text = "A class drawing multiline and aligned text on pictures";
//設(shè)置字體顏色
$black = imagecolorallocate($img, 65, 65, 65);
//將ttf文字寫到圖片中
imagettftext($img, 16, 0, 52, 170, $black, $font, $text);
//打印查看:
header('Content-Type: image/png;charset=UTF-8');//必須聲明
imagepng($img);
exit;
可以看到堡牡,當(dāng)文本超長時,直接被截斷了杨刨,超出圖片寬度的文字直接不可見晤柄。事實上崩溪,使用GD庫為圖片添加文字水印吉捶,它是不處理文本長度的。我們可以理解GD庫只處理圖片有多少個像素組成龙优,圖片長寬多少做粤,每一個像素點A(x,y)是什么顏色。
但是我們動態(tài)生成的圖片捉撮,不確定性太多怕品,例如用戶昵稱,用戶簽名巾遭,商品名稱等等這些長度都不確定肉康,造成了我們生成的圖片的文本長度不確定闯估,如果文本超出了,那么我們需要怎樣去處理超長的文本呢吼和?
答案是涨薪,自己去處理,通過自己設(shè)置的字體大小炫乓,圖片的寬度刚夺,計算出多少個字之后,就會被截斷末捣,在截斷之前自己生成新的字符串寫在第二行上面侠姑。
關(guān)鍵函數(shù):
$box = imagettfbbox ( 20, 0,$font, $ccv );
根據(jù) $box 提供的信息適當(dāng)裁剪 $ccv 使之可以放下
四,stil/gd-text的引入
但是人生苦短箩做,研究技術(shù)的小伙伴可以自己去搞一搞莽红,但是打工人時間緊任務(wù)重,gd-text這個包已經(jīng)幫我們封裝好了我們想要的東西邦邦,就不建議重復(fù)造輪子了安吁,我們直接使用。
它的使用方法類似于我們在PPT上面添加一個文本框一樣:給它一個左上角坐標(biāo)A(x,y)燃辖,寬度鬼店,高度。一個文本框就形成了郭赐,那我們在這個框里面寫東西薪韩,超出的文字就會自動換行。是不是非常方便
1捌锭,安裝:使用composer安裝:
composer require stil/gd-text
2俘陷,使用:
<?php
require __DIR__.'./vendor/autoload.php';
use GDText\Box;
use GDText\Color;
//1,添加一個畫布$img观谦,同時給這個畫布添加背景圖片$bg
$bgPath = './images/bg.jpg';
$bgInfo = getimagesize($bgPath);
$bgFun = 'imagecreatefrom'.image_type_to_extension($bgInfo[2], false);
//創(chuàng)建一個圖: 460*830
$bg = $bgFun($bgPath);
$bgWidth = imagesx($bg); //背景寬度
$bgHeight = imagesy($bg); //背景高度
$img = imageCreatetruecolor($bgWidth,$bgHeight);
$color = imagecolorallocate($img, 0, 0, 0);
imagefill($img, 0, 0, $color);
//平滑的拷貝背景圖到$img
imagecopyresampled($img,$bg,0,0,0,0,imagesx($bg),imagesy($bg),imagesx($bg),imagesy($bg));
//3拉盾,使用gd-text包來為圖片添加文字:
$box = new Box($img);
$font = realpath("./font/simhei.ttf");
//顯示的文字
$text = "A class drawing multiline and aligned text on pictures";
$box->setFontFace($font);
$box->setFontColor(new Color(77, 77, 77));//字體顏色
$box->setFontSize(18);//字體大小
$box->setLineHeight(1.5);//行高
//下面為關(guān)鍵函數(shù):畫一個文本框:
$box->setBox(52, 200, 370, 200);//文本框起始點(x,y),長寬
//第一個參數(shù)設(shè)置水平:靠左-left豁状,居中-center捉偏,靠右-right;第二個參數(shù)設(shè)置垂直:靠左-left泻红,居中-center夭禽,靠右-right
$box->setTextAlign('left', 'top');
$box->draw($text);
//再畫一個,這個是水平居中對齊的文本框:
$box->setBox(52, 380, 370, 200);
$box->setTextAlign('center', 'top');
$box->draw($text);
//打印查看:
header('Content-Type: image/png;charset=UTF-8');//必須聲明
imagepng($img);
exit;
3谊路,可以看到非常方便讹躯,但是當(dāng)我們的傳入的文本為中文時,奇怪的事情發(fā)生了,它并不能自動換行潮梯?骗灶??(手動黑人問號臉)秉馏。網(wǎng)上沒啥資料耙旦,自己看源代碼了。
五萝究,修改源代碼
通過查看gd-text包的源碼免都,我們可以發(fā)現(xiàn),它是在src/Box.php里面的wrapTextWithOverflow()方法實現(xiàn)換行的糊肤。原來琴昆,當(dāng)文本填滿第一行時,它是通過空格拆分一串字符的馆揉,這很好理解业舍,例如我們第一行八個單詞排上去,還差3個字母升酣,就要填滿第一行了舷暮,而第九個單詞(International)有13個字母,按照慣例我們不會把這個單詞的前3個字母給拆掉的噩茄,而是整個單詞都寫在第二行去下面。所有,它內(nèi)部是用explode()這個函數(shù)根據(jù)空格去拆單詞绩聘,然后逐個計算在那里換行的沥割。
但是我們的中文并不是每個字后面都有空格,explode()函數(shù)分隔符為必傳凿菩,那怎么辦呢机杜?
1,自己在每個字后面加1個空格衅谷,這樣就能自動換行椒拗。但是這樣字距很大,并不美觀获黔。
2蚀苛,str_split(string,length)函數(shù),它可以分割字符串玷氏,第二個參數(shù)為分割后每個字符的長度堵未。
但是分完后你會發(fā)現(xiàn)全是是亂碼,因為中文一個字占三個字節(jié)盏触,英文字母占一個字節(jié)渗蟹;
那我當(dāng)要插入中文的時候侦厚,用str_split(string,3)不就好了嗎?當(dāng)插入英文拙徽,就用explode();完美诗宣!
并不膘怕,很多時候我們都不敢保證一段就一定是英文或者是中文,它還有可能中文夾雜著英文召庞,那這時候岛心,依然是亂碼。
這時候篮灼,還有其他辦法嗎忘古?有,我們用強大的正則表達式
3诅诱,使用正則表達式
這個方法可以真正完全解決問題髓堪,下面我們開始修改源代碼:
事實上我們是不建議直接改擴展包里面的源碼的,這樣不規(guī)范娘荡,但是現(xiàn)在先略過
1干旁,在src/Box.php里面添加一個方法:
/**
* 拆分字符串為數(shù)組
* @param $str
* @author shaochao 2021/3/23 21:22
* @return array|false|string[]
*/
protected function mb_str_split($str){
return preg_split('/(?<!^)(?!$)/u', $str );
}
2,修改wrapTextWithOverflow()方法,加多一個參數(shù)炮沐,用來判斷用那種方法截取字符串:英文文本用空格争群;中文、中英混合文本用正則
/**
* Splits overflowing text into array of strings.
* @param string $text
* @return string[]
*/
protected function wrapTextWithOverflow($text,$isChinese = false)
{
$lines = array();
// Split text explicitly into lines by \n, \r\n and \r
$explicitLines = preg_split('/\n|\r\n?/', $text);
foreach ($explicitLines as $line) {
// Check every line if it needs to be wrapped
if($isChinese){
$words = $this->mb_str_split($line);
}else{
$words = explode(" ", $line);
}
$line = $words[0];
for ($i = 1; $i < count($words); $i++) {
$box = $this->calculateBox($line." ".$words[$i]);
if (($box[4]-$box[6]) >= $this->box['width']) {
$lines[] = $line;
$line = $words[$i];
} else {
$line .= $words[$i];
}
}
$lines[] = $line;
}
return $lines;
}
3大年,修改draw()方法换薄,加多一個參數(shù),用來判斷用那種方法截取字符串:英文文本用空格翔试;中文轻要、中英混合文本用正則
/**
* Draws the text on the picture.
* @param string $text Text to draw. May contain newline characters.
*/
public function draw($text,$isChinese = false)
{
if (!isset($this->fontFace)) {
throw new \InvalidArgumentException('No path to font file has been specified.');
}
switch ($this->textWrapping) {
case TextWrapping::NoWrap:
$lines = array($text);
break;
case TextWrapping::WrapWithOverflow:
default:
$lines = $this->wrapTextWithOverflow($text,$isChinese);
break;
}
//只改上面這幾行,該方法下面的代碼維持不變
4遏餐,使用draw()方法的時候伦腐,遇到中文文本,我們第二個參數(shù)傳true就可以了失都。
//4柏蘑,使用gd-text包來添加一段中文文本:
$text2 = '你好,世界粹庞,學(xué)無止境咳焚。你好,世界庞溜,學(xué)無止境革半。你好碑定,世界,學(xué)無止境又官。你好延刘,世界,學(xué)無止境六敬。你好碘赖,世界,學(xué)無止境外构。';
$box->setBox(52, 550, 370, 200);
$box->setTextAlign('left', 'top');
$box->draw($text2,true);
至此普泡,使用GD庫為圖片添加文字且自動換行的分享到此結(jié)束,希望對你有所幫助审编。
下一次分享使用GD庫動態(tài)生成分銷海報