先上效果图
图中黄色背景为生成的图片
参考:
https://blog.youkuaiyun.com/admin_o1/article/details/106320147
https://blog.youkuaiyun.com/dujiaoxi/article/details/80148460
下面看源码:
<?php
/**
* 需求 :
* 1.表头字段可以自定义,比如说两列、三列、四列(暂未实现)
* 2.表格列宽,可以根据表格内文字多少进行自动调整宽度(实现)
* 3.增加默认10行,不够10行补齐(实现)
*/
$data = [
'title' =>'标题',
'rows' =>10,//默认10行,不够10行补齐
'bgColor' =>[255,255,170],//生成的图片背景色
'name' =>mt_rand(1000,9999), //生成的图片名称
'font_url' =>'./font/fangzheng.ttf', //字体路径
'border' =>10,//外边框
'file_path' =>'./uploads/',//图片保存路径
'title_height' =>30,//报表名称高度
'title_font_size' =>16, //报表名称字体大小
'text_size' =>12, //正文字体大小
'row_height' =>30,//行高
'filed_id_width' =>40,//序号列宽度
'filed_name_width' => 100,//列名称的宽度
'filed_data_width' => 110,//数据列的宽度
'header_height' =>30,//表格上方,title下方高度
'margin' =>2, //表格外边框宽度
'header' =>['序号','型号','商品','数量','单价(元)','金额(元)'],//表头文字
'footer' =>'总计:1000元', //表格末尾
'footer_height' =>30,//表格末尾高度
'filed_width' =>[40,50,200,70,70,70],
'data' =>[
[
'xinghao' =>'0001',
'goods' =>'商品123',
'num' =>20,
'price' =>20.33,
'total' =>406.6
],
[
'xinghao' =>'0002',
'goods' =>'商品',
'num' =>20,
'price' =>20.33,
'total' =>406.6
],
], //数据
];
// function create_table_image($title,$data,$code,$buyer){
function create_table_image($data){
if(!isset($data['file_path']) || !$data['file_path']){
echo '请设置保存路径';
return false;
}
if(!isset($data['font_url']) || !$data['font_url']){
echo '请设置字体路径';
return false;
}
if(!isset($data['rows']) || !$data['rows']){
$data['rows'] = 10;
}
if(!isset($data['filed_width'])){
echo '请设置列宽';
return false;
}
foreach($data['data'] as $item){
$arr=array_keys($item);
for ($i=0; $i < count($arr); $i++) {
$table_header=imagettfbbox($data['text_size'],0,realpath($data['font_url']),$item[$arr[$i]]); //8个坐标
$font_width = $table_header[2] - $table_header[0];
if($data['filed_width'][$i+1] < $font_width){
$data['filed_width'][$i+1] = $font_width+20;
}
}
}
if(count($data['data'])< $data['rows']){
$new = [];
for($i=0;$i<($data['rows']-count($data['data']));$i++){
$tmp=[
];
$new[] = $tmp;
}
$data['data'] = array_merge($data['data'],$new);
}
$params = [
'row' => count($data['data']) + 1,//数据的行数
'file_name' => $data['name'] . '.png',
'title' => $data['title'],
'table_time' => date('Y-m-d H:i:s'),
'data' => $data['data']
];
$total_price = 0;
foreach($data['data'] as $item){
if($item['total']){
$total_price+=$item['total']*1;
}
}
$total_price_text = '合计:'. $total_price .'元';
$base = [
'border' => isset($data['border']) ? $data['border'] : 10,//图片外边框
'file_path' => $data['file_path'],//图片保存路径
'title_height' => isset($data['title_height']) ? $data['title_height'] : 30,//报表名称高度
'title_font_size' => isset($data['title_font_size']) ? $data['title_font_size'] : 16,//报表名称字体大小
'font_url' => realpath($data['font_url']),//字体文件路径
'text_size' => isset($data['text_size']) ? $data['text_size'] : 12,//正文字体大小
'row_hight' => isset($data['row_height']) ? $data['row_height'] : 30,//每行数据行高
'filed_id_width' => isset($data['filed_id_width']) ? $data['filed_id_width'] : 40,//序号列的宽度
'filed_name_width' => 100,//列名称的宽度
'filed_data_width' => 110,//数据列的宽度
'filed_width' =>$data['filed_width'],
'table_header' => $data['header'],//表头文字
'column_text_offset_arr' => [2,8,100,0,0,0],//表头文字左偏移量
'row_text_offset_arr' => [30,5,10,10,10,10],//数据列文字左偏移量
'total_height' =>isset($data['footer_height']) ? $data['footer_height'] : 30,//底部总计高度
'header_height' =>isset($data['header_height']) ? $data['footer_height'] : 30,
'margin' =>isset($data['margin']) ? $data['margin'] :2, //边框宽度
];
$sum_width=0;
foreach($data['filed_width'] as $item){
$sum_width+=$item;
}
$base['img_width'] = $sum_width + $base['border'] * 2;//图片宽度
$base['img_height'] = $params['row'] * $base['row_hight'] + $base['border'] * 2 + $base['title_height'] + $base['total_height'] + $base['header_height'];//图片高度
$border_top = $base['border'] + $base['title_height'] + $base['header_height'];//表格顶部高度
$border_bottom = $base['img_height'] - $base['border'] - $base['total_height'];//表格底部高度
//计算每一列的位置
foreach ($base['filed_width'] as $key => $value) {
//图片总宽
$w_sum += $value;
//计算每一列的位置
$base['column_x_arr'][$key] = $w_sum+$base['border'];
}
$img = imagecreatetruecolor($base['img_width'], $base['img_height']);//创建指定尺寸图片
$bg_color = imagecolorallocate($img, $data['bgColor'][0], $data['bgColor'][1], $data['bgColor'][2]);//设定图片背景色
$text_coler = imagecolorallocate($img, 0, 0, 0);//设定文字颜色
$border_coler = imagecolorallocate($img, 255, 0, 0);//设定边框颜色
$white_coler = imagecolorallocate($img, 255, 255, 255);//设定边框颜色
imagefill($img, 0, 0, $bg_color);//填充图片背景色
//先填充一个黑色的大块背景
imagefilledrectangle($img, $base['border'], $border_top, $base['img_width'] - $base['border'], $base['img_height'] - $base['border'] - $base['total_height'], $border_coler);//画矩形
//再填充一个小两个像素的 背景色区域,形成一个两个像素的外边框
imagefilledrectangle($img, $base['border'] + $base['margin'], $border_top+$base['margin'], $base['img_width'] - $base['border'] - $base['margin'], $base['img_height'] - $base['border']- $base['total_height'] - $base['margin'], $bg_color);//画矩形
// 画表格纵线 及 写入表头文字
foreach($base['column_x_arr'] as $key => $x){
imageline($img, $x, $border_top, $x, $border_bottom,$border_coler);//画纵线
$table_header=imagettfbbox($base['text_size'],0,$base['font_url'],$base['table_header'][$key]); //8个坐标
$font_width = $table_header[2] - $table_header[0];
imagettftext($img, $base['text_size'], 0, $x - $font_width - $base['column_text_offset_arr'][$key], $border_top + $base['row_hight'] - $base['hight']/2 - $base['text_size'] , $text_coler, $base['font_url'], $base['table_header'][$key]);//写入表头文字
}
//画表格横线
foreach($params['data'] as $key => $item){
$border_top += $base['row_hight'];
imageline($img, $base['border'], $border_top, $base['img_width'] - $base['border'], $border_top, $border_coler);
imagettftext($img, $base['text_size'], 0, $base['column_x_arr'][0] - $base['row_text_offset_arr'][0], $border_top + $base['row_hight'] - 10, $text_coler, $base['font_url'], $key + 1);//写入序号
$sub = 0;
foreach ($item as $value){
$sub++;
$table_header=imagettfbbox($base['text_size'],0,$base['font_url'],$value); //8个坐标
$font_width = $table_header[2] - $table_header[0];
imagettftext($img, $base['text_size'], 0, $base['column_x_arr'][$sub] - $font_width - $base['row_text_offset_arr'][$sub], $border_top + $base['row_hight'] - 10, $text_coler, $base['font_url'], $value);//写入data数据
}
}
//计算标题写入起始位置
$title_fout_box = imagettfbbox($base['title_font_size'], 0, $base['font_url'], $params['title']);//imagettfbbox() 返回一个含有 8 个单元的数组表示了文本外框的四个角:
$title_fout_width = $title_fout_box[2] - $title_fout_box[0];//右下角 X 位置 - 左下角 X 位置 为文字宽度
$title_fout_height = $title_fout_box[1] - $title_fout_box[7];//左下角 Y 位置- 左上角 Y 位置 为文字高度
//计算合计内容写入起始位置
$total_fout_box = imagettfbbox(10, 0, $base['font_url'], $total_price_text);//imagettfbbox() 返回一个含有 8 个单元的数组表示了文本外框的四个角:
$total_fout_width = $total_fout_box[2] - $total_fout_box[0];//右下角 X 位置 - 左下角 X 位置 为文字宽度
$total_fout_height = $total_fout_box[1] - $total_fout_box[7];//左下角 Y 位置- 左上角 Y 位置 为文字高度
//居中写入标题
imagettftext($img, $base['title_font_size'], 0, ($base['img_width'] - $title_fout_width)/2, $base['title_height'], $text_coler, $base['font_url'], $params['title']);
//写入制表时间
imagettftext($img, $base['text_size'], 0, $base['border'], $base['title_height'], $text_coler, $base['font_url'], '时间:' . $params['table_time']);
//写入买家信息
imagettftext($img, $base['text_size'], 0, $base['border'], $base['title_height']+20, $text_coler, $base['font_url'], '买家:' . '嘻嘻');
//写入合计信息
imagettftext($img, $base['text_size'], 0, $base['border']+50, $border_bottom + 20, $text_coler, $base['font_url'], $total_price_text);
//imagettftext ( resource $image , float $size , float $angle , int $x , int $y , int $color , string $fontfile , string $text )
$save_path = $base['file_path'] . $params['file_name'];
if(!is_dir($base['file_path']))//判断存储路径是否存在,不存在则创建
{
mkdir($base['file_path'],0777,true);//可创建多级目录
}
imagepng($img,$save_path);
return $save_path;
}
$url = create_table_image($data);
echo "<img src='$url'>";
?>