draw-poster.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. // 默认配置参数
  2. const defaultOptions = () => ({
  3. avatarUrl: 'https://static.caimei365.com/app/mini-hehe/icon/icon-join-us.png',
  4. userName: '采美',
  5. subTitle: '强烈为你推荐该商城',
  6. coverUrl: 'https://static.caimei365.com/app/mini-hehe/icon/icon-share.png',
  7. bgImageUrl: 'https://static.caimei365.com/app/mini-hehe/icon/bg-share-01.png',
  8. userBg: 'https://static.caimei365.com/app/img/icon/bg-card.png',
  9. userTitleBg: 'https://static.caimei365.com/app/img/icon/logo-fanbai.png',
  10. ewmUrl: 'https://static.caimei365.com/app/mini-hehe/icon/icon-ewm-hehe.jpg',
  11. textArray: [],
  12. scale: 0.5,
  13. })
  14. // 绘制海报
  15. export default class DrawPoster {
  16. constructor(ctx, options = {}) {
  17. this.ctx = ctx
  18. this.options = Object.assign(defaultOptions(), options)
  19. console.log('配置信息为:', this.options)
  20. }
  21. // 开始绘制
  22. draw() {
  23. return new Promise(async (resolve, reject) => {
  24. try {
  25. await this.drawBgImage()
  26. // await this.drawHeader()
  27. await this.drawUserCoverImage()
  28. await this.drawCenterInfo()
  29. } catch (e) {
  30. console.log(e)
  31. reject(e)
  32. } finally {
  33. this.ctx.draw(true, res => {
  34. resolve(true)
  35. })
  36. }
  37. })
  38. }
  39. // 绘制背景
  40. async drawBgImage() {
  41. try {
  42. const { bgImageUrl, scale } = this.options
  43. const [error, result] = await uni.downloadFile({ url: bgImageUrl })
  44. if (error) return
  45. this.ctx.setFillStyle('#999999')
  46. this.ctx.save()
  47. return Promise.resolve(true)
  48. } catch (e) {
  49. return Promise.reject(e)
  50. }
  51. }
  52. // 绘制圆角矩形
  53. async drawRoundRect(x, y, w, h, r) {
  54. this.ctx.beginPath()
  55. this.ctx.moveTo(x + r , y)
  56. this.ctx.arcTo(x + w, y, x + w, y + h, r)
  57. this.ctx.arcTo(x + w, y + h, x , y + h, r)
  58. this.ctx.arcTo(x, y + h, x, y, r)
  59. this.ctx.arcTo(x, y, x + w, y , r)
  60. this.ctx.setFillStyle('#FFFFFF')
  61. this.ctx.fill()
  62. this.ctx.clip()
  63. }
  64. // 绘制中心区域
  65. async drawCenterInfo() {
  66. try {
  67. const { scale } = this.options
  68. this.ctx.beginPath()
  69. this.drawRoundRect(28 * scale, 28 * scale, 694 * scale, 878 * scale, 8)
  70. await this.drawCoverImage()
  71. await this.drawFooterText()
  72. await this.drawEwmImage()
  73. return Promise.resolve(true)
  74. } catch (e) {
  75. return Promise.reject(e)
  76. }
  77. }
  78. // 绘制封面图片
  79. async drawCoverImage() {
  80. try {
  81. const { coverUrl, scale } = this.options
  82. const [error, result] = await uni.downloadFile({ url: coverUrl })
  83. if (error) return
  84. this.ctx.drawImage(result.tempFilePath, 56 * scale, 56 * scale, 638 * scale, 658 * scale)
  85. return Promise.resolve(true)
  86. } catch (e) {
  87. return Promise.reject(e)
  88. }
  89. }
  90. // 绘制名片封面
  91. async drawUserCoverImage() {
  92. try {
  93. const { userBg, scale, image, qrCode, linkMan, contractMobile } = this.options
  94. await this.drawBorderReduisImage(userBg, 28 * scale, 920 * scale, 694 * scale, 290 * scale, 8)
  95. await this.drawUserCardInner() // 绘制名片内容
  96. await this.drawCircleImg(image, 120 * scale, 1090 * scale, 30) //头像
  97. this.drawFontText(40 * scale, 200 * scale, 1070 * scale, '#fff', linkMan, 'bold')
  98. this.drawFontText(30 * scale, 200 * scale, 1130 * scale, '#fff', contractMobile, '400')
  99. await this.drawBorderReduisImage(qrCode, 520 * scale, 1000 * scale, 170 * scale, 170 * scale, 8)
  100. return Promise.resolve(true)
  101. } catch (e) {
  102. return Promise.reject(e)
  103. }
  104. }
  105. async drawUserCardInner() {
  106. try {
  107. const { userTitleBg, scale } = this.options
  108. const [error, result] = await uni.downloadFile({ url: userTitleBg })
  109. if (error) return
  110. this.ctx.drawImage(result.tempFilePath, 56 * scale, 940 * scale, 200 * scale, 70 * scale)
  111. return Promise.resolve(true)
  112. } catch (e) {
  113. return Promise.reject(e)
  114. }
  115. }
  116. async drawCircleImg(img, x, y, r) {
  117. const [error, result] = await uni.downloadFile({ url: img })
  118. console.log('result', result, x, y, r)
  119. if (error) return
  120. this.ctx.save()
  121. this.ctx.beginPath()
  122. let size = 2 * r
  123. this.ctx.arc(x, y, r, 0, 2 * Math.PI)
  124. this.ctx.clip()
  125. this.ctx.drawImage(result.tempFilePath, x - r, y - r, size, size)
  126. console.log('x - r, y - r, size, size', x - r, y - r, size, size)
  127. this.ctx.restore()
  128. }
  129. async drawBorderReduisImage(imgUrl, bg_x, bg_y, bg_w, bg_h, bg_r) {
  130. const [error, result] = await uni.downloadFile({ url: imgUrl })
  131. if (error) return
  132. this.ctx.save()
  133. this.ctx.beginPath()
  134. this.ctx.arc(bg_x + bg_r, bg_y + bg_r, bg_r, Math.PI, Math.PI*1.5)
  135. this.ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_r, bg_r, Math.PI * 1.5, Math.PI * 2)
  136. this.ctx.arc(bg_x + bg_w - bg_r, bg_y + bg_h - bg_r, bg_r, 0, Math.PI * 0.5)
  137. this.ctx.arc(bg_x + bg_r, bg_y + bg_h - bg_r, bg_r, Math.PI * 0.5, Math.PI)
  138. this.ctx.clip()
  139. this.ctx.drawImage(result.tempFilePath, bg_x, bg_y, bg_w, bg_h)
  140. this.ctx.restore()
  141. }
  142. // 绘制文字
  143. drawFontText(fontsize, x, y, color, text, bold) {
  144. this.ctx.beginPath()
  145. this.ctx.font = `${bold} ${fontsize}px sans-serif`
  146. this.ctx.setFillStyle(color)
  147. this.ctx.fillText(text, x, y)
  148. }
  149. // 绘制底部
  150. drawFooterText(callback) {
  151. const { scale, textArray } = this.options
  152. if (callback) {
  153. callback({ scale, ctx: this.ctx, textArray })
  154. } else {
  155. textArray.forEach((txt, index) => {
  156. this.ctx.setFontSize(30 * scale)
  157. this.ctx.setFillStyle('#333')
  158. this.ctx.fillText(txt, 56 * scale, (710 + 56 * index) * scale)
  159. })
  160. }
  161. }
  162. // 绘制底部二维码
  163. async drawEwmImage() {
  164. try {
  165. const { ewmUrl, scale } = this.options
  166. const [error, result] = await uni.downloadFile({ url: ewmUrl })
  167. if (error) return
  168. this.ctx.drawImage(result.tempFilePath, 524 * scale, 720 * scale, 160 * scale, 160 * scale)
  169. return Promise.resolve(true)
  170. } catch (e) {
  171. return Promise.reject(e)
  172. }
  173. }
  174. }