源代码
<?php
/**
*
* @authors Your Name (you@example.org)
* @date 2019-07-18 15:20:32
* @version $Id$
*/
namespace App\Tools;
class Poster
{
/**
* 生成宣传海报
* @param array 参数,包括图片和文字
* @param string $filename 生成海报文件名,不传此参数则不生成文件,直接输出图片
* @return [type] [description]
*/
public static function createPoster($config = array(), $filename = "", $ext = 'jpg')
{
//如果要看报什么错,可以先注释调这个header
if (empty($filename)) {
// header("content-type: image/png");
}
$imageDefault = array(
'left' => 0,
'top' => 0,
'right' => 0,
'bottom' => 0,
'width' => 100,
'height' => 100,
'opacity' => 100,
);
$textDefault = array(
'text' => '',
'left' => 0,
'top' => 0,
'fontSize' => 32, //字号
'fontColor' => '255,255,255', //字体颜色
'angle' => 0,
);
$background = $config['background']; //海报最底层得背景
//背景方法
$backgroundInfo = getimagesize($background);
$backgroundFun = 'imagecreatefrom' . image_type_to_extension($backgroundInfo[2], false);
$background = $backgroundFun($background);
$backgroundWidth = imagesx($background); //背景宽度
$backgroundHeight = imagesy($background); //背景高度
$imageRes = imageCreatetruecolor($backgroundWidth, $backgroundHeight);
if ($ext == 'png') {
imagealphablending($imageRes, false);
imagesavealpha($imageRes, true);
}
imagecopyresampled($imageRes, $background, 0, 0, 0, 0, imagesx($background), imagesy($background), imagesx($background), imagesy($background));
//处理了图片
if (!empty($config['image'])) {
foreach ($config['image'] as $key => $val) {
if ($val && is_array($val) && file_exists($val['url'])) {
$val = array_merge($imageDefault, $val);
$info = getimagesize($val['url']);
$function = 'imagecreatefrom' . image_type_to_extension($info[2], false);
if ($val['stream']) {
//如果传的是字符串图像流
$info = getimagesizefromstring($val['url']);
$function = 'imagecreatefromstring';
}
$res = $function($val['url']);
// v($function);
$resWidth = $info[0];
$resHeight = $info[1];
//建立画板 ,缩放图片至指定尺寸
$canvas = imagecreatetruecolor($val['width'], $val['height']);
//2.上色 //防止png透明背景变黑
$color = imagecolorallocate($canvas, 255, 255, 255);
//3.设置透明
imagecolortransparent($canvas, $color);
imagefill($canvas, 0, 0, $color);
//设定图像的混色模式
imagealphablending($res, true);
//关键函数,参数(目标资源,源,目标资源的开始坐标x,y, 源资源的开始坐标x,y,目标资源的宽高w,h,源资源的宽高w,h)
imagecopyresampled($canvas, $res, 0, 0, 0, 0, $val['width'], $val['height'], $resWidth, $resHeight);
//圆形生成
if ($val['is_circular'] == 1) {
$canvas = self::markRound($canvas, $val['width'], $val['height']);
}
$val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) - $val['width'] : $val['left'];
$val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) - $val['height'] : $val['top'];
//放置图像
imagecopymerge($imageRes, $canvas, $val['left'], $val['top'], $val['right'], $val['bottom'], $val['width'], $val['height'], $val['opacity']); //左,上,右,下,宽度,高度,透明度
}
}
}
//处理文字
if (!empty($config['text'])) {
foreach ($config['text'] as $key => $val) {
if ($val && is_array($val)) {
$val = array_merge($textDefault, $val);
list($R, $G, $B) = explode(',', $val['fontColor']);
$fontColor = imagecolorallocate($imageRes, $R, $G, $B);
$val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) : $val['left'];
$val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) : $val['top'];
$tmplist = self::autoLineSplit($val['text'], $val['fontPath'], $val['fontSize'], 'utf8', $val['width']);
foreach ($tmplist as $k => $v) {
$h = $val['top'] + $k * 30;
imagettftext($imageRes, $val['fontSize'], $val['angle'], $val['left'], $h, $fontColor, $val['fontPath'], $v);
}
}
}
}
//生成图片
if (!empty($filename)) {
switch ($ext) {
case 'jpg':
$res = imagejpeg($imageRes, $filename, 80); //保存到本地
break;
case 'png':
$res = imagepng($imageRes, $filename, 7); //保存到本地
break;
}
// var_dump($filename);
imagedestroy($imageRes);
if (!$res) {
return false;
}
return $filename;
} else {
imagejpeg($imageRes); //在浏览器上显示
imagedestroy($imageRes);
}
}
//生成圆形图片
public static function markRound($src_img, $w, $h)
{
$img = imagecreatetruecolor($w, $h);
//这一句一定要有
imagesavealpha($img, true);
//拾取一个完全透明的颜色,最后一个参数127为全透明
$bg = imagecolorallocatealpha($img, 59, 105, 138, 127);
imagefill($img, 0, 0, $bg);
$r = $w / 2; //圆半径
$y_x = $r; //圆心X坐标
$y_y = $r; //圆心Y坐标
for ($x = 0; $x < $w; $x++) {
for ($y = 0; $y < $h; $y++) {
$rgbColor = imagecolorat($src_img, $x, $y);
if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
imagesetpixel($img, $x, $y, $rgbColor);
}
}
}
return $img;
}
/*
* 绘图文字分行函数
* by COoL
* - 输入:
* str: 原字符串
* fontFamily: 字体
* fontSize: 字号
* charset: 字符编码
* width: 限制每行宽度(px)
* - 输出:
* 分行后的字符串数组
*/
public static function autoLineSplit($str, $fontFamily, $fontSize, $charset, $width)
{
$result = [];
$len = (strlen($str) + mb_strlen($str, $charset)) / 2;
// 计算总占宽
$dimensions = imagettfbbox($fontSize, 0, $fontFamily, $str);
$textWidth = abs($dimensions[4] - $dimensions[0]);
// 计算每个字符的长度
$singleW = $textWidth / $len;
// 计算每行最多容纳多少个字符
$maxCount = floor($width / $singleW);
while ($len > $maxCount) {
// 成功取得一行
$result[] = mb_strimwidth($str, 0, $maxCount, '', $charset);
// 移除上一行的字符
$str = str_replace($result[count($result) - 1], '', $str);
// 重新计算长度
$len = (strlen($str) + mb_strlen($str, $charset)) / 2;
}
// 最后一行在循环结束时执行
$result[] = $str;
return $result;
}
/**
* 制作文本信息数据
* @param type $param
*/
public static function toMarkTxt($name, $left = 0, $top = 0, $width = 400, $fontSize = 18, $fontColor = '0,0,0')
{
if ($name) {
$font = base_path() . '/public/upload/app/poster/SourceHanSansCN_Normal.otf';
$info = [
'text' => $name,
'left' => $left,
'top' => $top,
'fontSize' => $fontSize, //字号
'fontColor' => $fontColor, //字体颜色
'angle' => 0,
'width' => $width,
'fontPath' => $font,
];
return $info;
}
return [];
}
/**
* 制作文本信息数据
* @param type $param
*/
public static function toMarkImg($imgUrl, $left = 0, $top = 0, $width = 300, $height = 200, $is_circular = 0)
{
$info = [
'url' => $imgUrl,
'left' => $left,
'top' => $top,
'right' => 0,
'bottom' => 0,
'width' => $width,
'height' => $height,
'opacity' => 100,
'is_circular' => $is_circular,
];
return $info;
}
/**
* 制作货运合同
*/
public static function markHYHT($orderInfo, $qm1 = '', $qm2 = '')
{
# 背景信息
$config['background'] = base_path() . '/public/upload/app/poster/hyht_1200.jpg';
$order_sn = $orderInfo['order_sn'];
$store_name = $orderInfo['store_name'];
$user_name = $orderInfo['car_driver'];
$goods_name = $orderInfo['order_name'];
$start_address = $orderInfo['line_start'] . $orderInfo['start_address'];
$end_address = $orderInfo['line_end'] . $orderInfo['end_address'];
$car_sn = $orderInfo['car_sn'];
$car_type = $orderInfo['car_type'];
# 文字展示信息
$nowDate = date('Y-m-d', time());
$txt[] = self::toMarkTxt($store_name, 340, 370); //甲方
$txt[] = self::toMarkTxt($user_name, 340, 410, 400); //乙方
$txt[] = self::toMarkTxt($store_name, 320, 530); //
$txt[] = self::toMarkTxt($goods_name, 180, 570);
$txt[] = self::toMarkTxt($goods_name, 300, 650); //货物名
$txt[] = self::toMarkTxt('暂无', 765, 650); //货物价值
$txt[] = self::toMarkTxt("{$start_address}-{$end_address}", 355, 690, 700, 16); //起运地
$txt[] = self::toMarkTxt($car_sn, 280, 730); //车牌号
$txt[] = self::toMarkTxt($car_type, 745, 730); //车辆类型
$txt[] = self::toMarkTxt($store_name, 300, 1175); //甲方
$txt[] = self::toMarkTxt($nowDate, 300, 1220); //甲方日期
$txt[] = self::toMarkTxt($user_name, 815, 1175); //甲方
$txt[] = self::toMarkTxt($nowDate, 815, 1220); //甲方日期
$txt = array_filter($txt);
$config['text'] = $txt;
// # 签名展示信息
// $qm1 = base_path() . '/public/upload/app/poster/qm1.jpg';
// $qm2 = base_path() . '/public/upload/app/poster/qm2.jpg';
if ($qm1) {
$qm1 = base_path() . '/public' . $qm1;
$image[] = self::toMarkImg($qm1, 180, 1280);
}
if ($qm2) {
$qm2 = base_path() . '/public' . $qm2;
$image[] = self::toMarkImg($qm2, 710, 1280);
}
$config['image'] = $image;
$filePath = base_path() . "/storage/app/uploads/poster/contract/{$order_sn}.jpg";
if (file_exists($filePath)) {
@unlink($filePath);
}
Poster::createPoster($config, $filePath);
return "/uploads/poster/contract/{$order_sn}.jpg";
}
}