Poster.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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;
  10. use Grafika\Color;
  11. use Grafika\Grafika;
  12. use app\common\model\dealer\Setting;
  13. /**
  14. * 分销二维码
  15. * Class Qrcode
  16. * @package app\common\service
  17. */
  18. class Poster extends Base
  19. {
  20. /* @var \app\common\model\dealer\User $dealer 分销商用户信息 */
  21. private $dealer;
  22. /* @var array $config 分销商海报设置 */
  23. private $config;
  24. /**
  25. * 构造方法
  26. * Poster constructor.
  27. * @param $dealer
  28. * @throws \Exception
  29. */
  30. public function __construct($dealer)
  31. {
  32. parent::__construct();
  33. // 分销商用户信息
  34. $this->dealer = $dealer;
  35. // 分销商海报设置
  36. $this->config = Setting::getItem('qrcode', $dealer['wxapp_id']);
  37. }
  38. /**
  39. * 获取分销二维码
  40. * @return string
  41. * @throws \app\common\exception\BaseException
  42. * @throws \think\exception\DbException
  43. * @throws \Exception
  44. */
  45. public function getImage()
  46. {
  47. if (file_exists($this->getPosterPath())) {
  48. return $this->getPosterUrl();
  49. }
  50. // 小程序id
  51. $wxappId = $this->dealer['wxapp_id'];
  52. // 1. 下载背景图
  53. $backdrop = $this->saveTempImage($wxappId, $this->config['backdrop']['src'], 'backdrop');
  54. // 2. 下载用户头像
  55. $avatarUrl = $this->saveTempImage($wxappId, $this->dealer['user']['avatarUrl'], 'avatar');
  56. // 3. 下载小程序码
  57. $qrcode = $this->saveQrcode($wxappId, 'uid:' . $this->dealer['user_id']);
  58. // 4. 拼接海报图
  59. return $this->savePoster($backdrop, $avatarUrl, $qrcode);
  60. }
  61. /**
  62. * 海报图文件路径
  63. * @return string
  64. */
  65. private function getPosterPath()
  66. {
  67. // 保存路径
  68. $tempPath = WEB_PATH . 'temp' . DS . $this->dealer['wxapp_id'] . DS;
  69. !is_dir($tempPath) && mkdir($tempPath, 0755, true);
  70. return $tempPath . $this->getPosterName();
  71. }
  72. /**
  73. * 海报图文件名称
  74. * @return string
  75. */
  76. private function getPosterName()
  77. {
  78. return md5('poster_' . $this->dealer['user_id']) . '.png';
  79. }
  80. /**
  81. * 海报图url
  82. * @return string
  83. */
  84. private function getPosterUrl()
  85. {
  86. return \base_url() . 'temp/' . $this->dealer['wxapp_id'] . '/' . $this->getPosterName() . '?t=' . time();
  87. }
  88. /**
  89. * 拼接海报图
  90. * @param $backdrop
  91. * @param $avatarUrl
  92. * @param $qrcode
  93. * @return string
  94. * @throws \Exception
  95. */
  96. private function savePoster($backdrop, $avatarUrl, $qrcode)
  97. {
  98. // 实例化图像编辑器
  99. $editor = Grafika::createEditor(['Gd']);
  100. // 打开海报背景图
  101. $editor->open($backdropImage, $backdrop);
  102. // 生成圆形用户头像
  103. $this->config['avatar']['style'] === 'circle' && $this->circular($avatarUrl, $avatarUrl);
  104. // 打开用户头像
  105. $editor->open($avatarImage, $avatarUrl);
  106. // 重设用户头像宽高
  107. $avatarWidth = $this->config['avatar']['width'] * 2;
  108. $editor->resizeExact($avatarImage, $avatarWidth, $avatarWidth);
  109. // 用户头像添加到背景图
  110. $avatarX = $this->config['avatar']['left'] * 2;
  111. $avatarY = $this->config['avatar']['top'] * 2;
  112. $editor->blend($backdropImage, $avatarImage, 'normal', 1.0, 'top-left', $avatarX, $avatarY);
  113. // 生成圆形小程序码
  114. $this->config['qrcode']['style'] === 'circle' && $this->circular($qrcode, $qrcode);
  115. // 打开小程序码
  116. $editor->open($qrcodeImage, $qrcode);
  117. // 重设小程序码宽高
  118. $qrcodeWidth = $this->config['qrcode']['width'] * 2;
  119. $editor->resizeExact($qrcodeImage, $qrcodeWidth, $qrcodeWidth);
  120. // 小程序码添加到背景图
  121. $qrcodeX = $this->config['qrcode']['left'] * 2;
  122. $qrcodeY = $this->config['qrcode']['top'] * 2;
  123. $editor->blend($backdropImage, $qrcodeImage, 'normal', 1.0, 'top-left', $qrcodeX, $qrcodeY);
  124. // 写入用户昵称
  125. $fontSize = $this->config['nickName']['fontSize'] * 2 * 0.76;
  126. $fontX = $this->config['nickName']['left'] * 2;
  127. $fontY = $this->config['nickName']['top'] * 2;
  128. $Color = new Color($this->config['nickName']['color']);
  129. $fontPath = Grafika::fontsDir() . DS . 'st-heiti-light.ttc';
  130. $editor->text($backdropImage, $this->dealer['user']['nickName'], $fontSize, $fontX, $fontY, $Color, $fontPath);
  131. // 保存图片
  132. $editor->save($backdropImage, $this->getPosterPath());
  133. return $this->getPosterUrl();
  134. }
  135. /**
  136. * 生成圆形图片
  137. * @param static $imgpath 图片地址
  138. * @param string $saveName 保存文件名,默认空。
  139. */
  140. private function circular($imgpath, $saveName = '')
  141. {
  142. $srcImg = imagecreatefromstring(file_get_contents($imgpath));
  143. $w = imagesx($srcImg);
  144. $h = imagesy($srcImg);
  145. $w = $h = min($w, $h);
  146. $newImg = imagecreatetruecolor($w, $h);
  147. // 这一句一定要有
  148. imagesavealpha($newImg, true);
  149. // 拾取一个完全透明的颜色,最后一个参数127为全透明
  150. $bg = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
  151. imagefill($newImg, 0, 0, $bg);
  152. $r = $w / 2; //圆半径
  153. for ($x = 0; $x < $w; $x++) {
  154. for ($y = 0; $y < $h; $y++) {
  155. $rgbColor = imagecolorat($srcImg, $x, $y);
  156. if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
  157. imagesetpixel($newImg, $x, $y, $rgbColor);
  158. }
  159. }
  160. }
  161. // 输出图片到文件
  162. imagepng($newImg, $saveName);
  163. // 释放空间
  164. imagedestroy($srcImg);
  165. imagedestroy($newImg);
  166. }
  167. }