php 图片生成器
一.需求
最近公司由于有大量的海报要做,而且海报的布局规模都是一样的,只是内容不同,所以老板想我开发一个图片的生成器。可以根据你输入的内容生成海报图片。
具体有需求有以下的需求
1.可以根据将每条数据都是独立的
2.每条数据都必须居中,如果是数据很长的时候还要自动换行
3.可以将一个二维码生成在海报中,二维码是自己手动上传的
4.海报的长度是随着内容的大小而变化的
二.分析
因为目标文件为图片格式的,所以我想到的方法是使用php的gd库来生成图片。所以以上需求我是通过以下方式去解决的。
需求1解决方法,因为数据是一次性数据的,这是为了方便市场工作这样子设置的。所以我只能通过添加标识符来切割数据
需求2解决方法,通过设置每行最长宽度来分割每条数据,并计算每天数据的长度,然后计算出文字位置的偏移量,这里提示一下imagettfbbox()函数可以计算文字段落的长度
需求3解决方法,通过上传文件然后将二维码转化为规定规格的图片,再定位到画布中即可
需求4解决方法,通过计算数据的行数,标题以及二维码的总高度,然后设置画布的长度
三.实现过程
----------------------------------------------html-------------------------------------------------------------------------------------------------------------------------------
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0"> <title>海报自助生成器</title> <link rel="stylesheet" type="text/css" href="./css/zui.min.css"> <script src="./jquery-3.2.1.min.js"></script> <style> p{ text-align: center; } form{ width: 90%; max-width: 500px; margin: 0 auto; line-height: 1.8; } input.form-control{ border:1px solid #72a197; outline: none; } select.form-control{ border-color:#72a197; } select.form-control:focus{ outline: none; border-color:#72a197; box-shadow:0 0 0; } .radio_space input { width: 16px; line-height: 0px; text-align: initial; padding: 0; } .container{ text-align: center; width: 100vw; height: 480px; overflow: hidden; margin: 0 auto; } .haibao{ width:100vw; } .recruit-title{} .img-uploading{ display:inline-block; width:100%; height:60px; line-height: 60px; margin-bottom:10px; border-radius: 3px; box-sizing: border-box; border:1px solid #72a197; position:relative; text-align: center; text-decoration: none !important; } .img-p{ /* position:absolute;*/ font-size:45px; height:60px; width:100%; font-weight:100; color:#72a197; /*left:calc(50% - 30px);*/ text-align:center; } .uploading{ width:100%; height:60px; opacity:0; position: absolute; top: 0px; } .create{ border: none !important; background:#ea6b51; color:#fff; text-shadow: none !important; } .welfare-title .txta{ margin:10px 0; width:100%; height:150px; border-radius: 8px; border:1px solid #72a197; outline: none; padding:10px; } .welfare-title .img-uploading{ border:1px solid #8d6e63; } .welfare-title .img-p{ color:#8d6e63; } .activity-title .txta{ margin:10px 0; width:100%; height:150px; border-radius: 8px; border:1px solid #72a197; outline: none; padding:10px; } .activity-title .img-uploading{ border:1px solid #78909c; } .activity-title .img-p{ color:#78909c; } </style> <script type="text/javascript"> function changeimg(imgvalue){ document.getElementById('haibao').src = "./template/t"+imgvalue+".jpg"; } </script> </head> <body> <p></p> <p>妈妈再也不担心我不会p图了</p> <form action="toImage.php" id= "uploadForm" class="space form-horizontal" method="POST" enctype="multipart/form-data" > <!-- 手机类型 1为安卓手机 2为苹果手机 --> <input type="hidden" name="phoneType" id="phoneType"> <div class="main" style="padding-top: 20px;"> <div class="activity-title"> <div class="form-group"> <label class="col-xs-2">标题:</label> <div class="col-md-6 col-xs-10"> <input class="form-control" name="title" placeholder="" /> </div> </div> <textarea class="txta" name="content"></textarea> <p style="color: red;">请在每条数据后面添加*</p> <p style="color: red;">同一条数据请不要手动换行*</p> </div> <a href="#" class="img-uploading"> <i class="img-p" id="symbol">+</i> <input type="file" name="file" class="uploading"> </a> <a href="#haibao" class="btn btn-block create" value="生成" onclick="doUpload();"> 生成 </a> </div> </form> <p style="margin-top: 20px;">请长按保存,不要直接右上角转发</p> <p id="exp">参考海报</p> <div class="container"> <img id="haibao" class="haibao" src="./template/t1.png"/> </div> <script> $(".uploading").on("change",function(){ if($(".uploading").val() != ""){ $("#symbol").text("二维码已上传"); $("#symbol").css("fontSize","20px"); } }); function doUpload() { var formData = new FormData($( "#uploadForm" )[0]); $.ajax({ url: 'toImage.php' , type: 'POST', data: formData, async: false, cache: false, contentType: false, processData: false, success: function (returndata) { $("#haibao").attr("src",returndata); $("#exp").hide(); }, error: function (returndata) { } }); } </script> </body> </html>
下面是php文件信息
<?php /** * @param int $fontSize 字体大小 * @param resource $ttf 字体文件路径 * @param string $str 字符串 * @param array $data 数据数组容器 * @param int $textWidth 行宽 * @param int $textHeight 行高 * @param int $top 距离顶部距离 */ function toCenter($fontSize, $ttf, $str, &$data, $textWidth,$textHeight,&$top) { $length = mb_strlen($str,"utf-8"); $rowNum = 0; $count = count($data); $index = 0; for($i = 1; $i <= $length ; $i++ ) { $substr = mb_substr($str , $index , $i-$index,"utf-8"); // var_dump($substr); $width = getTextInfo($fontSize, $ttf, $substr)['width']; if($width >= $textWidth && $width <= ($textWidth + $fontSize*2)) { $index = $i; $data[$count+$rowNum]['top'] = $top; $data[$count+$rowNum]['left'] = (1129-$width)/2; $data[$count+$rowNum]['str'] = $substr; $data[$count+$rowNum]['fontSize'] = $fontSize; $rowNum++; $top += $textHeight; } } if($index!=$length){ $data[$count+$rowNum]['top'] = $top; $data[$count+$rowNum]['left'] = (1129-$width)/2; $data[$count+$rowNum]['str'] = $substr; $data[$count+$rowNum]['fontSize'] = $fontSize; $rowNum++; $top += $textHeight; } return $data; } function getTextInfo($fontSize, $ttf, $str) { $data = imagettfbbox($fontSize, 0, $ttf, $str); $width = $data[2]-$data[0]; $height = $data[1]-$data[7]; return [ 'width' => $width, 'height' => $height ]; } /** * 制作略缩图方法 * @param string $src 文件路径 * @param int $width 生成略缩图的宽度(只设置高度是则为等比例缩放) * @param int $height 生成略缩图的高度(只设置宽度是则为等比例缩放) * @param string $filename 生成略缩图图片保存路径 */ function makeThumb($src, $width = null, $height = null, $filename) { $srcData = getimagesize($src); list($srcWidth, $srcHeight, $srcType) = $srcData; if (empty($width)) $width = $srcWidth * ($height / $srcHeight); if (empty($height)) $height = $srcHeight * ($width / $srcWidth); switch ($srcType) { case '1': $imgType = 'gif'; break; case '2': $imgType = 'jpeg'; break; case '3': $imgType = 'png'; break; } $imageCreateFun = 'imagecreatefrom'.$imgType; $srcImg = $imageCreateFun($src); $destImg = imagecreatetruecolor(intval($width),intval($height)); imagecopyresampled($destImg, $srcImg,0,0,0,0,$width,$height,$srcWidth,$srcHeight); $imagefunc = 'image'.$imgType; $imagefunc($destImg,$filename.'.'.$imgType); return $filename.'.'.$imgType; } // // /************************************************处理二维码开始**************************************************************************/ $codePath = ''; $codeImageType = ''; if ((($_FILES["file"]["type"] == "image/jpeg")||($_FILES["file"]["type"] == "image/jpg")||($_FILES["file"]["type"] == "image/png"))&& ($_FILES["file"]["size"] < 2097152)) { if($_FILES["file"]["error"] > 0) { echo "发生错误" . $_FILES["file"]["error"] . ",请找TzSteady<br />"; exit; }else { move_uploaded_file($_FILES["file"]["tmp_name"],"./code/" . date("Ymd").$_FILES["file"]["name"]); $codePath = "./code/" . date("Ymd").$_FILES["file"]["name"]; $codePath = makeThumb($codePath,300,false,'./code/'.date("YmdHis")); $codeImageType = $_FILES["file"]["type"]; } }else { echo "<script> alert('请上传小于2M的jpg/png/jpeg格式的二维码'); </script>"; exit; } /******************************************************处理二维码结束********************************************************************/ $data = []; $titleTop = 300; $ttf = './ttf/fangzhengqingkebenyuesongjianti.TTF'; $titleData = []; $title = trim($_POST['title']); toCenter(65, $ttf, $title, $titleData, 700,100,$titleTop); $top =400; $str = trim($_POST['content']); $charArr = explode("*",$str); foreach ($charArr as $key => &$value) { $value = trim($value); if(empty($value)) continue; toCenter(30, $ttf, $value, $data, 800,60,$top); } $count = count($data); $fillNum = ceil(($count-3)+6); // /******************************画图开始********************************************/ $headerPath = './template/head.png'; $fillPath = './template/fill1.png'; $footerPath = './template/footer1.png'; $ttf = './ttf/fangzhengqingkebenyuesongjianti.TTF'; $header = imagecreatefrompng($headerPath); $fill = imagecreatefrompng($fillPath); $footer = imagecreatefrompng($footerPath); switch ($codeImageType) { case 'image/jpeg': $code = imagecreatefromjpeg($codePath); break; case 'image/jpg': $code = imagecreatefromjpeg($codePath); break; case 'image/png': $code = imagecreatefrompng($codePath); if(empty($code)) { $code = imagecreatefromjpeg($codePath); } break; } list($headerWidth,$headerHeight,$headerType) = getimagesize($headerPath); list($fillWidth,$fillHeight,$fillType) = getimagesize($fillPath); list($footerWidth,$footerHeight,$footerType) = getimagesize($footerPath); list($codeWidth,$codeHeight,$codeType) = getimagesize($codePath); $img = imagecreatetruecolor($headerWidth,$headerHeight+$fillHeight*$fillNum+$footerHeight); $result = imagecopy($img , $header,0,0,0,0,$headerWidth,$headerHeight); for($i = 0; $i < $fillNum ; $i++) { $result = imagecopy($img , $fill,0,$headerHeight+$fillHeight*$i,0,0,$fillWidth,$fillHeight); } $result = imagecopy($img , $footer,0,$headerHeight+$fillHeight*$fillNum,0,0,$footerWidth,$footerHeight); $result = imagecopy($img , $code,420,$fillHeight*($fillNum-1)+$headerHeight-30,0,0,$codeWidth,$codeHeight); $orange = ImageColorAllocate($img, 249,135,0); $white = ImageColorAllocate($img, 0,0,0); $titlered = ImageColorAllocate($img, 163,0,14); if(isset($titleData) && !empty($titleData)) { foreach ($titleData as $key => &$value) { imagettftext($img, $value['fontSize'], 0, $value['left'], $value['top'] , $titlered, $ttf,$value['str']); } } foreach ($data as $key => &$value) { imagettftext($img, $value['fontSize'], 0, $value['left'], $value['top'] , $white, $ttf,$value['str']); } imagettftext($img, 25, 0, 320 ,$headerHeight+$fillHeight*($fillNum-1)-50, $titlered, $ttf,'有兴趣的同学可以加微信咨询'); $filename = './img/'.date("Ymd-H-i-s").'.png'; imagepng($img,$filename); echo $filename; // /****************************画图结束**********************************************/