鸿宇研学生前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
5.6 KiB

  1. <template>
  2. <uv-popup
  3. ref="popup"
  4. :overlayOpacity="0.6"
  5. mode="center"
  6. bgColor="none"
  7. :zIndex="1000000"
  8. @change="onPopupChange"
  9. >
  10. <view class="popup__view">
  11. <view class="canvas" style="width: 566rpx; height: 1060rpx; overflow: hidden;">
  12. <canvas id="myCanvas" canvas-id="firstCanvas1" type="2d" style="width: 100%; height: 100%;"></canvas>
  13. </view>
  14. <button class="btn" @click="saveImg">
  15. <view class="content">保存到相册</view>
  16. </button>
  17. </view>
  18. </uv-popup>
  19. </template>
  20. <script>
  21. import { mapState } from 'vuex'
  22. export default {
  23. data() {
  24. return {
  25. path: '',
  26. wxCodeImage: '',
  27. baseUrl: 'https://image.hhlm1688.com/',
  28. canvas: {},
  29. retry: 10,
  30. }
  31. },
  32. computed: {
  33. ...mapState(['userInfo', 'configList']),
  34. },
  35. async onLoad() {
  36. },
  37. methods: {
  38. open(path) {
  39. this.path = path
  40. this.retry = 10
  41. this.$refs.popup.open();
  42. },
  43. close() {
  44. this.$refs.popup.close();
  45. },
  46. async fetchQrCode() {
  47. try {
  48. this.wxCodeImage = (await this.$fetch('getInviteCode', { path: this.path }))?.url
  49. } catch (err) {
  50. }
  51. },
  52. drawCoverImg(canvas, ctx, x, y, width, height) {
  53. return new Promise(resolve => {
  54. // 海报图片
  55. const paperImage = canvas.createImage()
  56. console.log('paperImage', paperImage)
  57. paperImage.src = this.configList.poster_image
  58. paperImage.onload = () => {
  59. console.log('paperImage onload')
  60. ctx.drawImage(paperImage, x, y, width, height)
  61. resolve()
  62. }
  63. })
  64. },
  65. drawQrCodeImg(canvas, ctx, x, y, size) {
  66. return new Promise(resolve => {
  67. //二维码图片
  68. const coderImage = canvas.createImage()
  69. coderImage.src = this.wxCodeImage
  70. coderImage.onload = () => {
  71. console.log('coderImage onload')
  72. ctx.drawImage(coderImage, x, y, size, size)
  73. resolve()
  74. }
  75. })
  76. },
  77. draw() {
  78. wx.createSelectorQuery().in(this)
  79. .select('#myCanvas') // 绘制的canvas的id
  80. .fields({
  81. node: true,
  82. size: true
  83. })
  84. .exec(async (res) => {
  85. console.log('res', res)
  86. if (!res?.[0]?.node) {
  87. if (!this.retry) {
  88. console.log('retry fail')
  89. return
  90. }
  91. console.log('retry')
  92. this.retry -= 1
  93. setTimeout(() => {
  94. this.draw()
  95. }, 200)
  96. return
  97. }
  98. const canvas = res[0].node
  99. // 渲染上下文
  100. const ctx = canvas.getContext('2d')
  101. // Canvas 画布的实际绘制宽高
  102. const width = res[0].width
  103. const height = res[0].height
  104. // 初始化画布大小
  105. const dpr = wx.getWindowInfo().pixelRatio
  106. //根据dpr调整
  107. // dpr 2 4
  108. // 3 6
  109. console.log("--dpr", dpr)
  110. canvas.width = width * dpr
  111. canvas.height = height * dpr
  112. let Ratio = canvas.width / 566
  113. this.canvas = canvas
  114. ctx.scale(dpr, dpr)
  115. ctx.clearRect(0, 0, width, height)
  116. ctx.fillStyle = 'transparent'
  117. ctx.fillRect(0, 0, canvas.width, canvas.height)
  118. ctx.save()
  119. let x = 0
  120. let y = 0
  121. let w = 566 * Ratio / dpr
  122. let h = 1060 * Ratio / dpr
  123. await this.drawCoverImg(canvas, ctx, x, y, w, h)
  124. ctx.restore();
  125. ctx.save()
  126. x = 316 * Ratio / dpr
  127. y = 810 * Ratio / dpr
  128. let size = 210 * Ratio / dpr
  129. await this.drawQrCodeImg(canvas, ctx, x, y, size)
  130. uni.hideLoading()
  131. })
  132. },
  133. async init() {
  134. uni.showLoading({
  135. title: '加载中...'
  136. });
  137. await this.fetchQrCode()
  138. uni.hideLoading();
  139. uni.showLoading({
  140. title: "拼命绘画中..."
  141. })
  142. this.draw()
  143. },
  144. saveImg() {
  145. this.$authorize('scope.writePhotosAlbum').then((res) => {
  146. this.imgApi()
  147. })
  148. },
  149. imgApi() {
  150. uni.showLoading({
  151. title: '保存中...'
  152. });
  153. wx.canvasToTempFilePath({
  154. x: 0,
  155. y: 0,
  156. width: this.canvas.width,
  157. height: this.canvas.height,
  158. canvas: this.canvas,
  159. success: (res) => {
  160. let tempFilePath = res.tempFilePath;
  161. this.saveImgToPhone(tempFilePath)
  162. },
  163. fail: (err) => {
  164. console.log('--canvasToTempFilePath--fail', err)
  165. uni.hideLoading();
  166. }
  167. }, this);
  168. },
  169. saveImgToPhone(image) {
  170. /* 获取图片的信息 */
  171. uni.getImageInfo({
  172. src: image,
  173. success: function(image) {
  174. /* 保存图片到手机相册 */
  175. uni.saveImageToPhotosAlbum({
  176. filePath: image.path,
  177. success: function() {
  178. uni.showModal({
  179. title: '保存成功',
  180. content: '图片已成功保存到相册',
  181. showCancel: false
  182. });
  183. },
  184. complete(res) {
  185. console.log(res);
  186. uni.hideLoading();
  187. }
  188. });
  189. }
  190. });
  191. },
  192. onPopupChange(e) {
  193. if (!e.show) {
  194. return
  195. }
  196. this.init()
  197. },
  198. },
  199. }
  200. </script>
  201. <style scoped lang="scss">
  202. .canvas {
  203. border-radius: 48rpx;
  204. }
  205. .btn {
  206. margin-top: 32rpx;
  207. width: 100%;
  208. padding: 22rpx 0;
  209. box-sizing: border-box;
  210. font-family: PingFang SC;
  211. font-weight: 500;
  212. font-size: 36rpx;
  213. line-height: 1.4;
  214. color: #FFFFFF;
  215. background: linear-gradient(to right, #21FEEC, #019AF9);
  216. border: 2rpx solid #00A9FF;
  217. border-radius: 41rpx;
  218. }
  219. </style>