2024-08-06 17:46:36 +08:00

205 lines
8.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace core\poster;
use Kkokk\Poster\Facades\Poster as PosterInstance;
class Poster extends BasePoster
{
/**
* @param array $config
* @return void
*/
protected function initialize(array $config = [])
{
parent::initialize($config);
}
/**
* 创建海报
* @param array $poster_data
* @param string $dir
* @param string $file_path
* @return mixed|string
* @throws \Exception
*/
public function createPoster(array $poster_data, string $dir, string $file_path)
{
$bg_type = $poster_data[ 'global' ][ 'bgType' ];
$instance = PosterInstance::extension('gd')->config([ 'path' => realpath($dir) . DIRECTORY_SEPARATOR . $file_path ]);
$bg_width = $poster_data[ 'global' ][ 'width' ];
$bg_height = $poster_data[ 'global' ][ 'height' ];
if ($bg_type == 'url' && !empty($poster_data[ 'global' ][ 'bgUrl' ]) && is_file($poster_data[ 'global' ][ 'bgUrl' ])) {
$im = $instance->buildIm($bg_width, $bg_height)->buildImage([
'src' => $poster_data[ 'global' ][ 'bgUrl' ],
// 'angle' => 80
], 0, 0, 0, 0, $bg_width, $bg_height);
} else {
$im = $instance->buildIm($bg_width, $bg_height, $this->getRgbColor($poster_data[ 'global' ][ 'bgColor' ]));
}
$align_array = [
'center', 'left', 'right', 'top', 'bottom'
];
foreach ($poster_data[ 'value' ] as $k => $v) {
$type = $v[ 'type' ];
switch ($type) {
case 'text':
$font_size = ceil($v[ 'fontSize' ]);
$default_font = 'static' . DIRECTORY_SEPARATOR . 'font' . DIRECTORY_SEPARATOR . 'SourceHanSansCN-Regular.ttf';
$font = $v[ 'fontFamily' ] ? : $default_font;
$content_list = $this->getText($v[ 'value' ], $font_size, $font, $v[ 'space' ] ?? 0, $v[ 'width' ], $v[ 'height' ], $v[ 'lineHeight' ] + $font_size);
$base_y = $this->getX($v[ 'y' ]);
if (is_array($base_y)) {
$diff_height = count($content_list) * ( $v[ 'lineHeight' ] + $font_size );
$again_y = $base_y[ 0 ];
if ($again_y == 'center') {
$base_y_num = ( $bg_height - $diff_height ) > 0 ? ( $bg_height - $diff_height ) / 2 : 0;
} else if ($again_y == 'top') {
$base_y_num = 0;
} else {
$base_y_num = $bg_height - $v[ 'height' ];
}
} else {
$base_y_num = $base_y;
}
// if(in_array($base_y, $align_array)){
// $diff_height = count($content_list)*($v[ 'lineHeight' ]+$font_size);
// $base_y_num = ($bg_height-$diff_height) > 0 ? ($bg_height-$diff_height)/2 : 0;
// }else{
// $base_y_num = $base_y[0];
// }
foreach ($content_list as $ck => $content) {
if ($ck == 0) {
if ($v[ 'lineHeight' ] > 0) {
$item_line = $v[ 'lineHeight' ] / 2;
} else {
$item_line = 0;
}
} else {
$item_line = $v[ 'lineHeight' ] + $font_size;
}
$base_y_num += $item_line;
//计算文本框宽度
$im = $im->buildText($content, $this->getX($v[ 'x' ]), $base_y_num, $font_size, $this->getRgbColor($v[ 'fontColor' ]), $v[ 'width' ], $font, $v[ 'weight' ] ? 10 : null); # 合成文字
}
break;
case 'image':
if (is_file($v[ 'value' ])) {
$im = $im->buildImage($v[ 'value' ], $this->getX($v[ 'x' ]), $this->getY($v[ 'y' ]), 0, 0, $v[ 'width' ], $v[ 'height' ], false, $v[ 'shape' ] ?? 'normal'); # 合成图片
}
break;
case 'draw':
if (!empty($v[ 'draw_type' ]) && $v[ 'draw_type' ] == 'Polygon') {
$points = $v[ 'points' ];
$im = $im->buildLine($points[ 0 ][ 0 ], $points[ 0 ][ 1 ], $points[ 2 ][ 0 ], $points[ 2 ][ 1 ], $this->getRgbColor($v[ 'bgColor' ]), 'filled_rectangle');
}
break;
}
}
$path = $im->getPoster();
return str_replace(DIRECTORY_SEPARATOR, '/', str_replace(realpath(''), '', $path[ 'url' ]));
}
public function getX($dst_x)
{
if (is_int($dst_x)) {
return $dst_x;
} else {
return [ $dst_x, 0 ];
}
}
public function getY($dst_y)
{
if (is_int($dst_y)) {
return $dst_y;
} else {
return [ $dst_y, 0 ];
}
}
public function getRgbColor($color)
{
$color = $color ? : '#FFFFFF';
if (!str_contains($color, '#')) {
$color = str_replace('rgba(', '', $color);
$color = str_replace(')', '', $color);
list($r, $g, $b) = explode(',', $color);
list($r, $g, $b) = array_map(function($v) { return (int) $v; }, [ $r, $g, $b ]);
} else {
list($r, $g, $b) = sscanf($color, "#%02x%02x%02x");
}
return [ $r, $g, $b, 1 ];
}
/**
* 获取高度限制过后的文本
* @param $content
* @param $fontSize
* @param $font
* @param $space
* @param $max_ws
* @param $max_hs
* @param $line_height
* @return mixed
*/
public function getText($content, $fontSize, $font, $space, $max_ws, $max_hs, $line_height)
{
$calcSpace = $space > $fontSize ? ( $space - $fontSize ) : 0; // 获取间距计算值
$fontSize = ( $fontSize * 3 ) / 4; // px 转化为 pt
mb_internal_encoding('UTF-8'); // 设置编码
// 这几个变量分别是 字体大小, 角度, 字体名称, 字符串, 预设宽度
$contents = '';
$contentsArr = [];
$letter = [];
$line = 1;
$calcSpaceRes = 0;
// 将字符串拆分成一个个单字 保存到数组 letter 中
for ($i = 0; $i < mb_strlen($content); $i++) {
$letter[] = mb_substr($content, $i, 1);
}
$textWidthArr = [];
$contentStr = '';
$line_num = 1;
$total_width = 0;
$content_list = [];
foreach ($letter as $l) {
$textStr = $contentStr . $l;
$fontBox = imagettfbbox($fontSize, 0, $font, $textStr);
$textWidth = abs($fontBox[ 2 ]) + $calcSpaceRes;
$textWidthArr[ $line ] = $textWidth;
// 判断拼接后的字符串是否超过预设的宽度
if (( $textWidth > $max_ws ) && ( $contents !== '' )) {
$line_num++;
if (( $line_num * $line_height ) > $max_hs) {
break;
}
$contents .= "\n";
$contentStr = "";
$line++;
}
if (empty($content_list[ $line_num - 1 ])) $content_list[ $line_num - 1 ] = '';
$content_list[ $line_num - 1 ] .= $l;
$contents .= $l;
$contentStr .= $l;
$line === 1 && $calcSpaceRes += $calcSpace;
$text_width = max(array_values($textWidthArr));
}
return $content_list;
}
}