第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 随机背景在随机位置添加随机颜色的文字

随机背景在随机位置添加随机颜色的文字

时间:2023-03-20 12:52:43

相关推荐

随机背景在随机位置添加随机颜色的文字

功能:根据给的中文字符串,取随机的图片为背景,将字符串中的每个字都随机显示在图片上,并偏斜一定的角度。

后端图片处理类,会返回图片对应的宽、高、旋转角度、旋转前起始x、y及文字四个角的x、y坐标:

class Image {/*** 图片上增加文字* @param type $strImgPath* @param type $arrText*/public function imgAddText($strText, $intWidth, $intHeight) {//随机取背景图片$strImgPath = $this->RandomFile(__DIR__ . '/verifycodeimages/', 'jpg|png');if (empty($strImgPath) || !file_exists($strImgPath)) {return null;}//获取图片信息$imgInfo = getimagesize($strImgPath);$imgRes = null;switch ($imgInfo[2]) {case 1:$imgRes = @imagecreatefromgif($strImgPath);break;case 2:$imgRes = @imagecreatefromjpeg($strImgPath);break;case 3:$imgRes = @imagecreatefrompng($strImgPath);break;}//重新设置图片大小$intPicWidth = imagesx($imgRes);$intPicHeight = imagesy($imgRes);if (function_exists("imagecopyresampled")) {$newImgRes = imagecreatetruecolor($intWidth, $intHeight);imagecopyresampled($newImgRes, $imgRes, 0, 0, 0, 0, $intWidth, $intHeight, $intPicWidth, $intPicHeight);} else {$newImgRes = imagecreate($intWidth, $intHeight);imagecopyresized($newImgRes, $imgRes, 0, 0, 0, 0, $intWidth, $intHeight, $intPicWidth, $intPicHeight);}//释放原图资源imagedestroy($imgRes);//设置字体信息$strFont = __DIR__ . '/Font/shoushu.ttf';$arrTextRange = array();$intFontSize = 30;$arrXY = array();for ($intNum = 0; $intNum < mb_strlen($strText, 'utf-8'); $intNum++) {//随机获取旋转角度$intAngle = rand(-45, 45);//随机获取文字颜色$color = imagecolorallocate($newImgRes, rand(0, 255), rand(0, 255), rand(0, 255));//获取文字所占像素位置$arrBox = imagettfbbox($intFontSize, $intAngle, $strFont, mb_substr($strText, $intNum, 1));$arrTureBox = imagettfbbox($intFontSize, 0, $strFont, mb_substr($strText, $intNum, 1));if ($arrBox) {$intMinX = min(array($arrBox[0], $arrBox[2], $arrBox[4], $arrBox[6]));$intMaxX = max(array($arrBox[0], $arrBox[2], $arrBox[4], $arrBox[6]));$intMinY = min(array($arrBox[1], $arrBox[3], $arrBox[5], $arrBox[7]));$intMaxY = max(array($arrBox[1], $arrBox[3], $arrBox[5], $arrBox[7]));$intFontWidth = $intMaxX - $intMinX;$intFontHeight = $intMaxY - $intMinY;$intX = $intY = 0;$intRangeMaxX = $intWidth - $intFontWidth;$intRangeMaxY = $intHeight - $intFontHeight;$arrRange = array();if (empty($arrXY)) {//如果没有画过文字,那整张图片都可以画$arrRange[] = array(0, 0, $intRangeMaxX, $intRangeMaxY);} else {//按x轴排序,判断排除前后几个字后,其他几个字y轴方向是否还有空间array_multisort(array_column($arrXY, 0), SORT_ASC, $arrXY);for ($intXNum = 0; $intXNum <= count($arrXY); $intXNum++) {//取前一个字的右侧x轴为最小x$intTempMinX = ($intXNum == 0 ? 0 : $arrXY[$intXNum - 1][2]);//获取右侧的边界值个数for ($intLen = count($arrXY) - $intXNum + 1; $intLen >= 1; $intLen--) {//取最后一个字的左侧x轴为最大x$intTempMaxX = ($intLen == count($arrXY) - $intXNum + 1 ? $intWidth : $arrXY[$intXNum + $intLen - 1][0]);$arrTempXY = array();if ($intLen > 1) {//文字区域按照y轴排序$arrTempXY = array_slice($arrXY, $intXNum, $intLen - 1);array_multisort(array_column($arrTempXY, 1), SORT_ASC, $arrTempXY);}//循环y轴区间for ($intYNum = 0; $intYNum <= count($arrTempXY); $intYNum++) {$intTempMinY = ($intYNum == 0 ? 0 : $arrTempXY[$intYNum - 1][3]);$intTempMaxY = ($intYNum == count($arrTempXY) ? $intHeight : $arrTempXY[$intYNum][1]);if ($intTempMaxY - $intTempMinY >= $intFontHeight && $intTempMaxX - $intTempMinX >= $intFontWidth) {$arrRange[] = array($intTempMinX, $intTempMinY, $intTempMaxX - $intFontWidth, $intTempMaxY - $intFontHeight);}}}}//按y轴排序,判断排除前后几个字后,其他几个字x轴方向是否还有空间array_multisort(array_column($arrXY, 1), SORT_ASC, $arrXY);for ($intYNum = 0; $intYNum <= count($arrXY); $intYNum++) {//取前一个字的下侧y轴为最小y$intTempMinY = ($intYNum == 0 ? 0 : $arrXY[$intYNum - 1][3]);//获取下侧的边界值个数for ($intLen = count($arrXY) - $intYNum + 1; $intLen >= 1; $intLen--) {//取最后一个字的上侧y轴为最大y$intTempMaxY = ($intLen == count($arrXY) - $intYNum + 1 ? $intHeight : $arrXY[$intYNum + $intLen - 1][1]);$arrTempXY = array();if ($intLen > 1) {//文字区域按照x轴排序$arrTempXY = array_slice($arrXY, $intYNum, $intLen - 1);array_multisort(array_column($arrTempXY, 0), SORT_ASC, $arrTempXY);}//循环x轴区间for ($intXNum = 0; $intXNum <= count($arrTempXY); $intXNum++) {$intTempMinX = ($intXNum == 0 ? 0 : $arrTempXY[$intXNum - 1][2]);$intTempMaxX = ($intXNum == count($arrTempXY) ? $intWidth : $arrTempXY[$intXNum][0]);if ($intTempMaxY - $intTempMinY >= $intFontHeight && $intTempMaxX - $intTempMinX >= $intFontWidth) {$arrRange[] = array($intTempMinX, $intTempMinY, $intTempMaxX - $intFontWidth, $intTempMaxY - $intFontHeight);}}}}}//随机取一块区域,在这一区域范围内获取位置$objRange = $arrRange[rand(0, count($arrRange) - 1)];$intX = rand($objRange[0], $objRange[2]);$intY = rand($objRange[1], $objRange[3]);$arrXY[] = array($intX, $intY, $intX + $intFontWidth, $intY + $intFontHeight);imagettftext($newImgRes, $intFontSize, $intAngle, $intX - $intMinX, $intY - $intMinY, $color, $strFont, mb_substr($strText, $intNum, 1));$intTrueWidth = max(array($arrTureBox[0], $arrTureBox[2], $arrTureBox[4], $arrTureBox[6])) - min(array($arrTureBox[0], $arrTureBox[2], $arrTureBox[4], $arrTureBox[6]));$intTrueHeight = max(array($arrTureBox[1], $arrTureBox[3], $arrTureBox[5], $arrTureBox[7])) - min(array($arrTureBox[1], $arrTureBox[3], $arrTureBox[5], $arrTureBox[7]));$arrTextRange[] = array('x' => $intX + ($intFontWidth - $intTrueWidth) / 2,'y' => $intY + ($intFontHeight - $intTrueHeight) / 2,'angle' => -$intAngle,'width' => $intTrueWidth,'height' => $intTrueHeight,'coordinate' => array(['x' => $arrBox[0] + $intX - $intMinX, "y" => $arrBox[1] + $intY - $intMinY],['x' => $arrBox[2] + $intX - $intMinX, "y" => $arrBox[3] + $intY - $intMinY],['x' => $arrBox[4] + $intX - $intMinX, "y" => $arrBox[5] + $intY - $intMinY],['x' => $arrBox[6] + $intX - $intMinX, "y" => $arrBox[7] + $intY - $intMinY]));}}ob_start();//$im是你自己创建的图片资源imagepng($newImgRes);imagedestroy($newImgRes);$image_data = ob_get_contents();ob_end_clean();//得到这个结果,可以直接用于前端的img标签显示$image_data_base64 = "data:image/png;base64," . base64_encode($image_data);return array('img' => $image_data_base64, 'range' => $arrTextRange);}/*** 随机获取文件名* @param type $strFileFolder* @param type $strExtensions* @return type*/function RandomFile($strFileFolder = '', $strExtensions = '.*') {// fix path:$strFileFolder = trim($strFileFolder);$strFileFolder = ($strFileFolder == '') ? './' : $strFileFolder;// check folder:if (!is_dir($strFileFolder)) {return "";}// create files array$arrFiles = array();// open directoryif ($strDir = @opendir($strFileFolder)) {// go trough all files:while ($strFile = readdir($strDir)) {if (!preg_match('/^\.+$/', $strFile) andpreg_match('/\.(' . $strExtensions . ')$/', $strFile)) {// feed the array:$arrFiles[] = $strFile;}}// close directoryclosedir($strDir);} else {return "";}if (count($arrFiles) == 0) {return "";}// seed random function:mt_srand((double) microtime() * 1000000);// get an random index:$intRand = mt_rand(0, count($arrFiles) - 1);// check again:if (!isset($arrFiles[$intRand])) {return "";}// return the random file:return $strFileFolder . $arrFiles[$intRand];}}

如需在前端验证返回的位置是否正确,可以按以下方式:

<!DOCTYPE html><html><head><meta charset="UTF-8"><title>verifycode</title><style type="text/css">body{margin: 0px;}</style><script src="/js/plugin/jquery-1.12.2.min.js"></script><script type="text/javascript">$('#imgverifycode').on('click', function () {console.log(event.offsetX + '|' + event.offsetY);});//描点,参数有点的大小,颜色,点的坐标和标签; 很明显opts参数是一个对象function drawPoint(opts) {document.write("<span id='" + opts.point[0] + "" + opts.point[1] + "' style='display: inline-block; width: " + opts.pw + "px; height: " + opts.ph + "px; background-color: " + opts.color + "; position: absolute;left: " + opts.point[0] + "px; top: " + opts.point[1] + "px;'>" + (opts.point[2] ? ("<div style='position: relative;'><span style='position: absolute; left: 5px; bottom: 1px; text-align: left; width: 100px;'>" + opts.point[2] + "</span></div>") : "") + "</span>");}//画线//pstart 起点//pend 终点//opts 参数function drawLine(pstart, pend, opts) {var ph = 1;var pw = 1;var color = "DarkRed";if (opts) {color = opts.color ? opts.color : color;}var slope; //斜率var noSlope = false; //是否有斜率var hdist = pend[0] - pstart[0];var vdist = pend[1] - pstart[1];if (hdist != 0) {slope = Math.abs(vdist / hdist); //计算斜率} else {noSlope = true; //当hdist=0时,直线没有斜率}var gapp = pw > ph ? ph : pw; //默认相邻点(左上角的像素点)间的距离var diagonal = Math.sqrt(Math.pow(hdist, 2) + Math.pow(vdist, 2)); //斜边长度var pn = parseInt(diagonal / gapp); //计算两点之间的点的数量if (pn < 3) {pn = pn * 3 + 1}; //如果点的数量小于3,则加大点数;为什么+1呢,是保证pn=0时至少有一个点var vgap = Math.abs(vdist) / pn; //相邻两点间的垂直距离var hgap = Math.abs(hdist) / pn; //相邻两点间的水平距离for (var i = 0; i < pn; i++) {//描点//hgap 相邻两点间的水平距离//vgap 相邻两点间的垂直距离//hgap*i*(pend[0]<pstart[0]?-1:1)*(noSlope?0:1) 相对于起点的水平偏移//vgap*i*(pend[1]<pstart[1]?-1:1) 相对于起点的垂直偏移//(pend[0]<pstart[0]?-1:1) 水平偏移方向//(pend[1]<pstart[1]?-1:1) 垂直偏移方向//(noSlope?0:1) 直线没有斜率时,水平偏移为0drawPoint({pw: pw,ph: ph,color: color,point: [(hgap * i * (pend[0] < pstart[0] ? -1 : 1) * (noSlope ? 0 : 1) + pstart[0]), (vgap * i * (pend[1] < pstart[1] ? -1 : 1) + pstart[1])]});}}//多边形//ps 点的一维数组function drawPolygon(ps) {if (ps) {//画线for (var i = 0; i < ps.length - 1; i++) {drawLine(ps[i], ps[i + 1]);}//使闭合if (ps.length > 2) {drawLine(ps[ps.length - 1], ps[0])}//描拐点for (var i = 0; i < ps.length; i++) {drawPoint({pw: 3,ph: 3,color: 'RED',point: ps[i]});}}}</script></head><body><div id="verifycodeDiv" style="width: 250px;height: 250px; position:relative;margin:200px 300px;"><?phpinclude_once dirname(__DIR__) . '/ComModule/.php';//获取图片$img = new Image();$img6VerifyCode = $img->imgAddText('我是中国人来自江苏', 250, 250);//显示图片echo '<img id="imgverifycode" src="' . $img6VerifyCode['img'] . '"/>';foreach ($img6VerifyCode['range'] as $arrRange) {//在图片上每个字上加一个div,看是否和文字重合,div偏斜角度同文字偏斜角度echo '<div pos="[' . $arrRange['coordinate'][0]['x'] . "," . $arrRange['coordinate'][0]['y'] . ']'. '[' . $arrRange['coordinate'][1]['x'] . "," . $arrRange['coordinate'][1]['y'] . ']'. '[' . $arrRange['coordinate'][2]['x'] . "," . $arrRange['coordinate'][2]['y'] . ']'. '[' . $arrRange['coordinate'][3]['x'] . "," . $arrRange['coordinate'][3]['y'] . ']" '. 'style="position:absolute;'. 'top:' . $arrRange['y'] . 'px;left:' . $arrRange['x'] . 'px;'. 'width:' . $arrRange['width'] . 'px;height:' . $arrRange['height'] . 'px;'. 'transform:rotate(' . $arrRange['angle'] . 'deg);">'. '</div>';//在图片上画矩形,看看矩形是否包含文字echo '<script type="text/javascript">drawPolygon(['. '[' . $arrRange['coordinate'][0]['x'] . ', ' . $arrRange['coordinate'][0]['y'] . '], '. '[' . $arrRange['coordinate'][1]['x'] . ', ' . $arrRange['coordinate'][1]['y'] . '],'. '[' . $arrRange['coordinate'][2]['x'] . ', ' . $arrRange['coordinate'][2]['y'] . '],'. '[' . $arrRange['coordinate'][3]['x'] . ', ' . $arrRange['coordinate'][3]['y'] . ']'. ']);</script>';}?></div></body></html>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。