| <template> | 
|     <view style="position: fixed;z-index: -9999;"> | 
|         <canvas id="myQrcode" :canvas-id="canvasID" :style="{width:canvasWidth+'px',height:canvasHeight+'px'}"></canvas> | 
|         <view v-if="qrCode == ''"> | 
|             <QRCode ref="qrcode" /> | 
|         </view> | 
|     </view> | 
| </template> | 
|   | 
| <script> | 
|     import QRCode from "../qr_code/qrcode.vue" | 
|     var _this; | 
|     export default { | 
|         name: 'canvas-images', | 
|         props: { | 
|             // canvasID 等同于 canvas-id | 
|             canvasID: { | 
|                 Type: String, | 
|                 default: 'myQrcode' | 
|             }, | 
|             canvasWidth: { // 画布宽度 | 
|                 Type: 'int', | 
|                 default: 375 | 
|             }, | 
|             canvasHeight: { // 画布高度 | 
|                 Type: 'int', | 
|                 default: 650 | 
|             }, | 
|             shareTitle: { // 分享标题 | 
|                 Type: 'String', | 
|                 default: '我是这张图片的标题' | 
|             }, | 
|             goodsTitle: { // 商品宣传标题 | 
|                 Type: 'String', | 
|                 default: '' | 
|             }, | 
|             goodsTitle2: { // 商品宣传标题 | 
|                 Type: 'String', | 
|                 default: '' | 
|             }, | 
|   | 
|             shareImage: { // 分享图片 | 
|                 Type: 'String', | 
|                 default: '' | 
|             }, | 
|             qrSize: { // 二维码大小 | 
|                 Type: 'int', | 
|                 default: 100 | 
|             }, | 
|             qrUrl: { // 生成二维码的链接 | 
|                 Type: 'String', | 
|                 default: 'https://ext.dcloud.net.cn/plugin?id=5747' | 
|             } | 
|         }, | 
|         components: { | 
|             QRCode | 
|         }, | 
|         data() { | 
|             return { | 
|                 qrCode: '', // 二维码 | 
|                 localImgPath: '', | 
|                 canvas: undefined | 
|             } | 
|         }, | 
|         mounted() { | 
|             _this = this; | 
|         }, | 
|         methods: { | 
|             // downloadImg() { | 
|             //     let that = this | 
|             //     const query = uni.createSelectorQuery() | 
|             //     console.log('canvasID',this.canvasID) | 
|             //     query.select('#myQrcode') | 
|             //         .fields({ | 
|             //             node: true, | 
|             //             size: true | 
|             //         }) | 
|             //         .exec((res) => { | 
|             //             console.log('query',res) | 
|             //             var canvas = res[0].node | 
|             //             uni.canvasToTempFilePath({ | 
|             //                 canvasId: this.canvasID, | 
|             //                 canvas: canvas, | 
|             //                 x: 0, | 
|             //                 y: 0, | 
|             //                 width: this.canvasWidth, | 
|             //                 height: this.canvasHeight, | 
|             //                 destWidth: this.canvasWidth, | 
|             //                 destHeight: this.canvasHeight, | 
|             //                 success(res) { | 
|             //                     console.log('二维码临时路径:', res.tempFilePath) | 
|             //                     uni.saveImageToPhotosAlbum({ | 
|             //                         filePath: res.tempFilePath, | 
|             //                         success: function() { | 
|             //                             console.log('save success'); | 
|             //                             uni.showToast({ | 
|             //                                 title: '保存成功' | 
|             //                             }) | 
|             //                         }, | 
|             //                         fail(res) { | 
|             //                             console.error(res) | 
|             //                             uni.showToast({ | 
|             //                                 title: '保存失败。', | 
|             //                                 icon: 'error' | 
|             //                             }) | 
|             //                         } | 
|             //                     }) | 
|             //                 }, | 
|             //                 fail(res) { | 
|             //                     console.error('fail', res) | 
|   | 
|             //                     uni.showToast({ | 
|             //                         title: '保存失败', | 
|             //                         icon: 'error' | 
|             //                     }) | 
|             //                 } | 
|             //             }) | 
|   | 
|             //         }) | 
|   | 
|             // }, | 
|   | 
|             // 创建二维码 | 
|             canvasCreate() { | 
|                 this.localImgPath = this.shareImage | 
|                 console.log('this.shareImage', this.shareImage) | 
|                 if (this.shareImage && this.shareImage.startsWith('https://')) { | 
|                     uni.getImageInfo({ | 
|                         src: _this.shareImage, | 
|                         success(res) { | 
|                             console.log('getImageInfo res', res) | 
|                             _this.localImgPath = res.path | 
|                             _this.$refs.qrcode.make({ | 
|                                     size: _this.qrSize, | 
|                                     text: _this.qrUrl | 
|                                 }) | 
|                                 .then(res => { | 
|                                     // 返回的res与uni.canvasToTempFilePath返回一致 | 
|                                     // console.log(res) | 
|                                     _this.qrCode = res.tempFilePath; | 
|                                     _this.onCanvas(); | 
|                                 }); | 
|                         }, | 
|                         fail(error) { | 
|                             this.$message.showToast('加载图片错误') | 
|                         } | 
|                     }) | 
|                 } else { | 
|                     _this.$refs.qrcode.make({ | 
|                             size: _this.qrSize, | 
|                             text: _this.qrUrl | 
|                         }) | 
|                         .then(res => { | 
|                             // 返回的res与uni.canvasToTempFilePath返回一致 | 
|                             // console.log(res) | 
|                             _this.qrCode = res.tempFilePath; | 
|                             _this.onCanvas(); | 
|                         }); | 
|                 } | 
|   | 
|   | 
|             }, | 
|             // 画图 | 
|             async onCanvas() { | 
|                 uni.showLoading({ | 
|                     title: "分享图片生成中..." | 
|                 }); | 
|                 const ctx = uni.createCanvasContext(_this.canvasID, _this); | 
|                 // 设置 canvas 背景色 | 
|                 ctx.setFillStyle('#FFFFFF'); | 
|                 ctx.fillRect(0, 0, _this.canvasWidth, _this.canvasHeight); | 
|                 ctx.setFillStyle('#000000'); | 
|                 // 背景图片 | 
|                 //需要下载图片 | 
|   | 
|                 if (_this.localImgPath) { | 
|                     console.log('localImgPath', _this.localImgPath) | 
|                     ctx.drawImage(_this.localImgPath, 20, 20, 335, 500); | 
|                 } | 
|                 // ctx.setFontSize(18); | 
|                 // ctx.setTextAlign('center'); | 
|                 // ctx.fillText(_this.shareTitle, _this.canvasWidth / 2, 30); | 
|                 // 左边标题 | 
|                 ctx.setTextAlign('left') | 
|                 ctx.setFontSize(22) | 
|                 _this.writeTextOnCanvas(ctx, 20, 21, _this.goodsTitle, 20, 560); | 
|                 ctx.setTextAlign('left') | 
|                 ctx.setFontSize(16) | 
|                 _this.writeTextOnCanvas(ctx, 20, 21, _this.goodsTitle2, 20, 585); | 
|                 // 设置虚线 | 
|                 // ctx.setStrokeStyle('#333333'); | 
|                 // ctx.setLineDash([5, 10], 2); | 
|                 // ctx.beginPath(); | 
|                 // ctx.moveTo(220, 340); | 
|                 // ctx.lineTo(220, 420); | 
|                 // ctx.stroke(); | 
|                 // 二维码 | 
|                 ctx.drawImage(_this.qrCode, 250, 520, 100, 100); | 
|                 // ctx.draw(); | 
|   | 
|                 // 延迟后渲染至canvas上 | 
|                 let pic = await _this.setTime(ctx) | 
|                 _this.$emit('success', pic); | 
|             }, | 
|             /** | 
|              * @param {Object} ctx_2d    getContext("2d") 对象 | 
|              * @param {int} lineheight    段落文本行高 | 
|              * @param {int} bytelength    设置单字节文字一行内的数量 | 
|              * @param {string} text        写入画面的段落文本 | 
|              * @param {int} startleft    开始绘制文本的 x 坐标位置(相对于画布) | 
|              * @param {int} starttop    开始绘制文本的 y 坐标位置(相对于画布) | 
|              */ | 
|             writeTextOnCanvas(ctx_2d, lineheight, bytelength, text, startleft, starttop) { | 
|                 // 获取字符串的真实长度(字节长度) | 
|                 function getTrueLength(str) { | 
|                     var len = str.length, | 
|                         truelen = 0; | 
|                     for (var x = 0; x < len; x++) { | 
|                         if (str.charCodeAt(x) > 128) { | 
|                             truelen += 2; | 
|                         } else { | 
|                             truelen += 1; | 
|                         } | 
|                     } | 
|                     return truelen; | 
|                 } | 
|                 // 按字节长度截取字符串,返回substr截取位置 | 
|                 function cutString(str, leng) { | 
|                     var len = str.length, | 
|                         tlen = len, | 
|                         nlen = 0; | 
|                     for (var x = 0; x < len; x++) { | 
|                         if (str.charCodeAt(x) > 128) { | 
|                             if (nlen + 2 < leng) { | 
|                                 nlen += 2; | 
|                             } else { | 
|                                 tlen = x; | 
|                                 break; | 
|                             } | 
|                         } else { | 
|                             if (nlen + 1 < leng) { | 
|                                 nlen += 1; | 
|                             } else { | 
|                                 tlen = x; | 
|                                 break; | 
|                             } | 
|                         } | 
|                     } | 
|                     return tlen; | 
|                 } | 
|                 for (var i = 1; getTrueLength(text) > 0; i++) { | 
|                     var tl = cutString(text, bytelength); | 
|                     ctx_2d.fillText(text.substr(0, tl).replace(/^\s+|\s+$/, ""), startleft, (i - 1) * lineheight + | 
|                         starttop); | 
|                     text = text.substr(tl); | 
|                 } | 
|             }, | 
|             // 彻底改成同步 防止拿到的图片地址为空 | 
|             setTime(ctx) { | 
|                 return new Promise((resole, err) => { | 
|                     setTimeout(() => { | 
|                         ctx.draw(false, async () => { | 
|                             let pic = await _this.getNewPic(); | 
|                             resole(pic) | 
|                         }); | 
|                     }, 600) | 
|                 }) | 
|             }, | 
|             // 获取新的图片地址 | 
|             getNewPic() { | 
|                 return new Promise((resolve, errs) => { | 
|                     setTimeout(() => { | 
|                         uni.canvasToTempFilePath({ | 
|                             canvasId: _this.canvasID, | 
|                             quality: 1, | 
|                             complete: (res) => { | 
|                                 // 在H5平台下,tempFilePath 为 base64 | 
|                                 // 关闭showLoading | 
|                                 uni.hideLoading(); | 
|                                 //  储存海报地址  也是分享的地址 | 
|                                 resolve(res.tempFilePath) | 
|                             } | 
|                         }, _this); | 
|                     }, 200) | 
|                 }) | 
|             }, | 
|         }, | 
|         mounted() { | 
|             _this = this; | 
|         } | 
|     } | 
| </script> |