Poster.php 5.7 KB

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