Goods.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. *
  4. * @copyright ©2020 点小铺
  5. * @author hanj
  6. * @link: https://dyuit.com
  7. * Created by VSCode
  8. */
  9. namespace app\common\service\qrcode\bargain;
  10. use Grafika\Color;
  11. use Grafika\Grafika;
  12. use app\common\service\qrcode\Base;
  13. class Goods extends Base
  14. {
  15. // 砍价活动信息
  16. private $active;
  17. // 商品信息
  18. private $goods;
  19. // 用户id
  20. private $user_id;
  21. /**
  22. * 构造方法
  23. * Goods constructor.
  24. * @param $active
  25. * @param $goods
  26. * @param $user
  27. */
  28. public function __construct($active, $goods, $user)
  29. {
  30. parent::__construct();
  31. // 砍价活动信息
  32. $this->active = $active;
  33. // 商品信息
  34. $this->goods = $goods;
  35. // 当前用户id
  36. $this->user_id = $user ? $user['user_id'] : 0;
  37. }
  38. /**
  39. * @return mixed
  40. * @throws \app\common\exception\BaseException
  41. * @throws \think\exception\DbException
  42. * @throws \Exception
  43. */
  44. public function getImage()
  45. {
  46. // 判断海报图文件存在则直接返回url
  47. if (file_exists($this->getPosterPath())) {
  48. return $this->getPosterUrl();
  49. }
  50. // 小程序id
  51. $wxappId = $this->active['wxapp_id'];
  52. // 商品海报背景图
  53. $backdrop = __DIR__ . '/../resource/goods_bg.png';
  54. // 下载商品首图
  55. $goodsUrl = $this->saveTempImage($wxappId, $this->goods['goods_image'], 'goods');
  56. // 小程序码参数
  57. $scene = "aid:{$this->active['active_id']},uid:" . ($this->user_id ?: '');
  58. // 下载小程序码
  59. $qrcode = $this->saveQrcode($wxappId, $scene, 'pages/bargain/goods/index');
  60. // 拼接海报图
  61. return $this->savePoster($backdrop, $goodsUrl, $qrcode);
  62. }
  63. /**
  64. * 拼接海报图
  65. * @param $backdrop
  66. * @param $goodsUrl
  67. * @param $qrcode
  68. * @return string
  69. * @throws \Exception
  70. */
  71. private function savePoster($backdrop, $goodsUrl, $qrcode)
  72. {
  73. // 实例化图像编辑器
  74. $editor = Grafika::createEditor(['Gd']);
  75. // 字体文件路径
  76. $fontPath = Grafika::fontsDir() . '/' . 'st-heiti-light.ttc';
  77. // 打开海报背景图
  78. $editor->open($backdropImage, $backdrop);
  79. // 打开商品图片
  80. $editor->open($goodsImage, $goodsUrl);
  81. // 重设商品图片宽高
  82. $editor->resizeExact($goodsImage, 690, 690);
  83. // 商品图片添加到背景图
  84. $editor->blend($backdropImage, $goodsImage, 'normal', 1.0, 'top-left', 30, 30);
  85. // 商品名称处理换行
  86. $fontSize = 30;
  87. $goodsName = $this->wrapText($fontSize, 0, $fontPath, $this->goods['goods_name'], 680, 2);
  88. // 写入商品名称
  89. $editor->text($backdropImage, $goodsName, $fontSize, 30, 750, new Color('#333333'), $fontPath);
  90. // 写入商品价格
  91. $editor->text($backdropImage, $this->active['floor_price'], 38, 62, 964, new Color('#ff4444'));
  92. // 打开小程序码
  93. $editor->open($qrcodeImage, $qrcode);
  94. // 重设小程序码宽高
  95. $editor->resizeExact($qrcodeImage, 140, 140);
  96. // 小程序码添加到背景图
  97. $editor->blend($backdropImage, $qrcodeImage, 'normal', 1.0, 'top-left', 570, 914);
  98. // 保存图片
  99. $editor->save($backdropImage, $this->getPosterPath());
  100. return $this->getPosterUrl();
  101. }
  102. /**
  103. * 处理文字超出长度自动换行
  104. * @param integer $fontsize 字体大小
  105. * @param integer $angle 角度
  106. * @param string $fontface 字体名称
  107. * @param string $string 字符串
  108. * @param integer $width 预设宽度
  109. * @param null $max_line 最多行数
  110. * @return string
  111. */
  112. private function wrapText($fontsize, $angle, $fontface, $string, $width, $max_line = null)
  113. {
  114. // 这几个变量分别是 字体大小, 角度, 字体名称, 字符串, 预设宽度
  115. $content = "";
  116. // 将字符串拆分成一个个单字 保存到数组 letter 中
  117. $letter = [];
  118. for ($i = 0; $i < mb_strlen($string, 'UTF-8'); $i++) {
  119. $letter[] = mb_substr($string, $i, 1, 'UTF-8');
  120. }
  121. $line_count = 0;
  122. foreach ($letter as $l) {
  123. $testbox = imagettfbbox($fontsize, $angle, $fontface, $content . ' ' . $l);
  124. // 判断拼接后的字符串是否超过预设的宽度
  125. if (($testbox[2] > $width) && ($content !== "")) {
  126. $line_count++;
  127. if ($max_line && $line_count >= $max_line) {
  128. $content = mb_substr($content, 0, -1, 'UTF-8') . "...";
  129. break;
  130. }
  131. $content .= "\n";
  132. }
  133. $content .= $l;
  134. }
  135. return $content;
  136. }
  137. /**
  138. * 海报图文件路径
  139. * @return string
  140. */
  141. private function getPosterPath()
  142. {
  143. // 保存路径
  144. $tempPath = WEB_PATH . 'temp' . '/' . $this->active['wxapp_id'] . '/';
  145. !is_dir($tempPath) && mkdir($tempPath, 0755, true);
  146. return $tempPath . $this->getPosterName();
  147. }
  148. /**
  149. * 海报图文件名称
  150. * @return string
  151. */
  152. private function getPosterName()
  153. {
  154. return 'bargain_active_' . md5("{$this->user_id}_{$this->active['active_id']}") . '.png';
  155. }
  156. /**
  157. * 海报图url
  158. * @return string
  159. */
  160. private function getPosterUrl()
  161. {
  162. return \base_url() . 'temp/' . $this->active['wxapp_id'] . '/' . $this->getPosterName() . '?t=' . time();
  163. }
  164. }