| <template> | |
|   <uv-popup  | |
|     ref="popup" | |
|     :overlayOpacity="0.6" | |
|     mode="center" | |
|     bgColor="none" | |
|     :zIndex="1000000" | |
|     @change="onPopupChange" | |
|   > | |
|     <view class="popup__view"> | |
|       <view class="canvas" style="width: 566rpx; height: 1060rpx; overflow: hidden;"> | |
|         <canvas id="myCanvas" canvas-id="firstCanvas1" type="2d" style="width: 100%; height: 100%;"></canvas> | |
|       </view> | |
| 
 | |
|       <button class="btn" @click="saveImg"> | |
|         <view class="content">保存到相册</view> | |
|       </button> | |
|     </view> | |
|   </uv-popup> | |
| </template> | |
| 
 | |
| 
 | |
| <script> | |
| 	import { mapState } from 'vuex' | |
| 
 | |
|   export default { | |
| 		data() { | |
| 			return { | |
|         path: '', | |
| 				wxCodeImage: '', | |
| 				baseUrl: 'https://image.hhlm1688.com/', | |
| 				canvas: {}, | |
|         retry: 10, | |
| 			} | |
| 		}, | |
|     computed: { | |
| 			...mapState(['userInfo', 'configList']), | |
|     }, | |
|     async onLoad() { | |
|     }, | |
|     methods: { | |
|       open(path) { | |
|         this.path = path | |
|         this.retry = 10 | |
|         this.$refs.popup.open(); | |
|       }, | |
|       close() { | |
|         this.$refs.popup.close(); | |
|       }, | |
| 			async fetchQrCode() { | |
| 				try { | |
| 					this.wxCodeImage = (await this.$fetch('getInviteCode', { path: this.path }))?.url | |
| 
 | |
| 				} catch (err) { | |
| 
 | |
| 				} | |
| 			}, | |
|       drawCoverImg(canvas, ctx, x, y, width, height) { | |
|         return new Promise(resolve => { | |
|           // 海报图片 | |
|           const paperImage = canvas.createImage() | |
|           console.log('paperImage', paperImage) | |
|           paperImage.src = this.configList.poster_image | |
|           paperImage.onload = () => { | |
|             console.log('paperImage onload') | |
|             ctx.drawImage(paperImage, x, y, width, height) | |
|             resolve() | |
|           } | |
|         }) | |
|       }, | |
|       drawQrCodeImg(canvas, ctx, x, y, size) { | |
|         return new Promise(resolve => { | |
|           //二维码图片 | |
|           const coderImage = canvas.createImage() | |
|           coderImage.src = this.wxCodeImage | |
|           coderImage.onload = () => { | |
|             console.log('coderImage onload') | |
|             ctx.drawImage(coderImage, x, y, size, size) | |
| 
 | |
|             resolve() | |
|           } | |
|         }) | |
|       }, | |
| 			draw() { | |
| 
 | |
| 				wx.createSelectorQuery().in(this) | |
| 					.select('#myCanvas') // 绘制的canvas的id | |
| 					.fields({ | |
| 						node: true, | |
| 						size: true | |
| 					}) | |
| 					.exec(async (res) => { | |
|             console.log('res', res) | |
|             if (!res?.[0]?.node) { | |
|               if (!this.retry) { | |
|                 console.log('retry fail') | |
|                 return | |
|               } | |
|               console.log('retry') | |
|               this.retry -= 1 | |
|               setTimeout(() => { | |
|                 this.draw() | |
|               }, 200) | |
|               return | |
|             } | |
| 						const canvas = res[0].node | |
| 						// 渲染上下文 | |
| 						const ctx = canvas.getContext('2d') | |
| 						// Canvas 画布的实际绘制宽高 | |
| 						const width = res[0].width | |
| 						const height = res[0].height | |
| 						// 初始化画布大小 | |
| 						const dpr = wx.getWindowInfo().pixelRatio | |
| 
 | |
| 						//根据dpr调整 | |
| 						// dpr  2 4 | |
| 						//      3 6 | |
| 						console.log("--dpr", dpr) | |
| 						canvas.width = width * dpr | |
| 						canvas.height = height * dpr | |
| 
 | |
| 						let Ratio = canvas.width / 566 | |
| 
 | |
| 						this.canvas = canvas | |
| 						ctx.scale(dpr, dpr) | |
| 						ctx.clearRect(0, 0, width, height) | |
| 
 | |
| 						ctx.fillStyle = 'transparent' | |
| 						ctx.fillRect(0, 0, canvas.width, canvas.height) | |
| 
 | |
|             ctx.save() | |
| 
 | |
|             let x = 0 | |
|             let y = 0 | |
|             let w = 566 * Ratio / dpr | |
|             let h = 1060 * Ratio / dpr | |
|             await this.drawCoverImg(canvas, ctx, x, y, w, h) | |
| 
 | |
|             ctx.restore(); | |
|             ctx.save() | |
| 
 | |
|             x = 316 * Ratio / dpr | |
|             y = 810 * Ratio / dpr | |
|             let size = 210 * Ratio / dpr | |
|             await this.drawQrCodeImg(canvas, ctx, x, y, size) | |
| 
 | |
|             uni.hideLoading() | |
| 
 | |
| 					}) | |
| 
 | |
| 			}, | |
|       async init() { | |
|         uni.showLoading({ | |
|             title: '加载中...' | |
|         }); | |
| 
 | |
|         await this.fetchQrCode() | |
|         uni.hideLoading(); | |
| 
 | |
| 				uni.showLoading({ | |
| 					title: "拼命绘画中..." | |
| 				}) | |
|         this.draw() | |
|       }, | |
| 			saveImg() { | |
| 				this.$authorize('scope.writePhotosAlbum').then((res) => { | |
| 					this.imgApi() | |
| 				}) | |
| 			}, | |
| 			imgApi() { | |
|         uni.showLoading({ | |
|             title: '保存中...' | |
|         }); | |
| 				wx.canvasToTempFilePath({ | |
| 					x: 0, | |
| 					y: 0, | |
| 					width: this.canvas.width, | |
| 					height: this.canvas.height, | |
| 					canvas: this.canvas, | |
| 					success: (res) => { | |
| 						let tempFilePath = res.tempFilePath; | |
| 						this.saveImgToPhone(tempFilePath) | |
| 					}, | |
| 					fail: (err) => { | |
| 						console.log('--canvasToTempFilePath--fail', err) | |
| 				    uni.hideLoading(); | |
| 					} | |
| 				}, this); | |
| 
 | |
| 			}, | |
| 			saveImgToPhone(image) { | |
| 				/* 获取图片的信息 */ | |
| 				uni.getImageInfo({ | |
| 					src: image, | |
| 					success: function(image) { | |
| 						/* 保存图片到手机相册 */ | |
| 						uni.saveImageToPhotosAlbum({ | |
| 							filePath: image.path, | |
| 							success: function() { | |
| 								uni.showModal({ | |
| 									title: '保存成功', | |
| 									content: '图片已成功保存到相册', | |
| 									showCancel: false | |
| 								}); | |
| 							}, | |
| 							complete(res) { | |
| 								console.log(res); | |
| 				        uni.hideLoading(); | |
| 							} | |
| 						}); | |
| 					} | |
| 				}); | |
| 			}, | |
|       onPopupChange(e) { | |
|         if (!e.show) { | |
|           return | |
|         } | |
| 
 | |
|         this.init() | |
|       }, | |
|     }, | |
|   } | |
| </script> | |
| 
 | |
| <style scoped lang="scss"> | |
|   .canvas { | |
|     border-radius: 48rpx; | |
|   } | |
| 
 | |
|   .btn { | |
|     margin-top: 32rpx; | |
|     width: 100%; | |
|     padding: 22rpx 0; | |
|     box-sizing: border-box; | |
|     font-family: PingFang SC; | |
|     font-weight: 500; | |
|     font-size: 36rpx; | |
|     line-height: 1.4; | |
|     color: #FFFFFF; | |
|     background: linear-gradient(to right, #21FEEC, #019AF9); | |
|     border: 2rpx solid #00A9FF; | |
|     border-radius: 41rpx; | |
|   } | |
| </style> |