|
|
@@ -3,14 +3,31 @@
|
|
|
namespace common\components;
|
|
|
|
|
|
/**
|
|
|
- * 散客分享海报(OSS 图片水印合成)
|
|
|
+ * 散客分享海报(OSS:poster/blank.png 动态画布 + 水印合成)
|
|
|
*/
|
|
|
class PosterUtil
|
|
|
{
|
|
|
- const BASE_TEMPLATE = 'poster/1234.jpg';
|
|
|
+ /** 与 poster/1234.jpg 同目录的 10×10 白底,经 m_pad 拉成本次海报画布 */
|
|
|
+ const BLANK_CANVAS = 'poster/blank.png';
|
|
|
|
|
|
const FONT = 'd3F5LW1pY3JvaGVp';
|
|
|
|
|
|
+ const POSTER_W = 750;
|
|
|
+
|
|
|
+ const SLOT_W = 700;
|
|
|
+
|
|
|
+ const FOOTER_H = 360;
|
|
|
+
|
|
|
+ const IMG_H_MIN = 480;
|
|
|
+
|
|
|
+ const IMG_H_MAX = 880;
|
|
|
+
|
|
|
+ const TOTAL_H_MIN = 840;
|
|
|
+
|
|
|
+ const TOTAL_H_MAX = 1600;
|
|
|
+
|
|
|
+ const CANVAS_COLOR = 'FFFFFF';
|
|
|
+
|
|
|
/**
|
|
|
* 海报标题过长时截断,避免压住底部文案区
|
|
|
*/
|
|
|
@@ -26,6 +43,45 @@ class PosterUtil
|
|
|
return $text;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 按商品图比例计算主图区高度与画布总高
|
|
|
+ *
|
|
|
+ * @return array{imgH:int,totalH:int,posterW:int}
|
|
|
+ */
|
|
|
+ public static function calcPosterLayout($coverWidth, $coverHeight)
|
|
|
+ {
|
|
|
+ $coverWidth = (int)$coverWidth;
|
|
|
+ $coverHeight = (int)$coverHeight;
|
|
|
+
|
|
|
+ if ($coverWidth > 0 && $coverHeight > 0) {
|
|
|
+ $scaledH = (int)round($coverHeight * (self::SLOT_W / $coverWidth));
|
|
|
+ $imgH = max(self::IMG_H_MIN, min(self::IMG_H_MAX, $scaledH));
|
|
|
+ } else {
|
|
|
+ $imgH = 720;
|
|
|
+ }
|
|
|
+
|
|
|
+ $totalH = $imgH + self::FOOTER_H;
|
|
|
+ $totalH = max(self::TOTAL_H_MIN, min(self::TOTAL_H_MAX, $totalH));
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'imgH' => $imgH,
|
|
|
+ 'totalH' => $totalH,
|
|
|
+ 'posterW' => self::POSTER_W,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 动态白底画布(blank.png → 750 × totalH)
|
|
|
+ */
|
|
|
+ public static function buildCanvasBaseUrl($prefix, $totalH)
|
|
|
+ {
|
|
|
+ $totalH = max(self::TOTAL_H_MIN, min(self::TOTAL_H_MAX, (int)$totalH));
|
|
|
+ $process = '?x-oss-process=image/resize,m_pad,w_' . self::POSTER_W . ',h_' . $totalH
|
|
|
+ . ',color_' . self::CANVAS_COLOR;
|
|
|
+
|
|
|
+ return $prefix . self::BLANK_CANVAS . $process;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 和炫鲜花等门店角标
|
|
|
*/
|
|
|
@@ -53,7 +109,7 @@ class PosterUtil
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 花材海报(与花束同一套版式)
|
|
|
+ * 花材海报(商城散客)
|
|
|
*/
|
|
|
public static function buildMallItemPosterUrl($prefix, array $options)
|
|
|
{
|
|
|
@@ -72,7 +128,7 @@ class PosterUtil
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 散客分享海报:主图 m_lfit、价格/标题/推荐人层次、扫码提示
|
|
|
+ * 散客/花束分享海报:动态画布 + 主图固定槽位 + 底部信息区
|
|
|
*/
|
|
|
private static function buildMallSharePosterUrl($prefix, array $options)
|
|
|
{
|
|
|
@@ -86,6 +142,16 @@ class PosterUtil
|
|
|
$subtitle = trim((string)($options['subtitle'] ?? ''));
|
|
|
$scanHint = trim((string)($options['scanHint'] ?? '微信扫码下单'));
|
|
|
|
|
|
+ $coverW = (int)($options['coverWidth'] ?? 0);
|
|
|
+ $coverH = (int)($options['coverHeight'] ?? 0);
|
|
|
+ if ($coverW <= 0 || $coverH <= 0) {
|
|
|
+ list($coverW, $coverH) = imgUtil::getOssImageSize($cover, $prefix);
|
|
|
+ }
|
|
|
+
|
|
|
+ $layout = self::calcPosterLayout($coverW, $coverH);
|
|
|
+ $imgH = $layout['imgH'];
|
|
|
+ $totalH = $layout['totalH'];
|
|
|
+
|
|
|
$displayName = self::truncateText($name, 14);
|
|
|
if ($flowerNum > 0 && $displayName !== '') {
|
|
|
$displayName .= ' · ' . $flowerNum . '支';
|
|
|
@@ -93,10 +159,10 @@ class PosterUtil
|
|
|
$displayName .= ' · ' . self::truncateText($subtitle, 8);
|
|
|
}
|
|
|
|
|
|
- $coverWatermark = $cover . '?x-oss-process=image/resize,m_lfit,h_1020,w_700,limit_0';
|
|
|
+ $coverWatermark = $cover . '?x-oss-process=image/resize,m_fill,h_' . $imgH . ',w_' . self::SLOT_W;
|
|
|
$qrWatermark = $miniCode . '?x-oss-process=image/resize,m_fill,h_220,w_220';
|
|
|
|
|
|
- $url = $prefix . self::BASE_TEMPLATE . '?x-oss-process=image';
|
|
|
+ $url = self::buildCanvasBaseUrl($prefix, $totalH);
|
|
|
$url .= '/watermark,image_' . stringUtil::ossBase64($coverWatermark) . ',g_north,x_25,y_8';
|
|
|
$url .= '/watermark,image_' . stringUtil::ossBase64($qrWatermark) . ',g_se,x_36,y_32';
|
|
|
|