<template> <view class="box"> <view style="padding-top: 100rpx;padding-left: 73rpx;padding-right: 75rpx;"> <view style="border-radius: 20rpx;"> <canvas canvas-id="mini_poster" style="width: 600rpx;" :style="{ height: canvasH + 'px' }"></canvas><!-- :style="{ width: canvasW + 'px', height: canvasH + 'px' }" --> </view> </view> <view style="height: 106rpx;"></view> <!-- <view class="footer"> <view style="height: 106rpx; align-items: center; background-color: #333333;"> <button style="background: transparent; height: 106rpx; line-height: 106rpx;" @tap="toSaveImage">保存名片</button> </view> </view> --> <view class="downloadBtn" @click="toSaveImage">保存图片</view> <!-- <img :src="mpWxQr2" alt="" ref="image" class="wcl"> --> </view> </template> <script> export default { data() { return { mpWxQr: "https://apidms.66km.com/static/third/jialian.ico", canvasW: 0, canvasH: 0, invest_areas: [{id: 1, name: "儿童教育"}, {id: 1, name: "大数据"}], nickname: "", avatar: "", company: "", phone: "17610998099", email: "redoume@163.com", time: "2022.01.21~2022.01.2", finished: false, sellingPoint:'', userInfo:'', ext:'', mpWxQr2:'', mpWxQr3:'', mpWxQr4:'', ptImg:'https://dmsimg.66km.com/marketing//accompany/4E6F0009-EC54-4387-8DDC-2B7389065B49.png', ptImg2:'', groupType:'', } }, computed: { showInvestAreas() { if (this.invest_areas) { const names = [] this.invest_areas.forEach(item => { names.push(item.name) }) return names.join(" ") } return '未设置' } }, onLoad(opt) { //this.canvasW = uni.getSystemInfoSync().windowWidth //this.canvasH = this.calculateCanvasHeight() this.avatar=opt.img; //this.avatar='http://dmsphoto.66km.com.cn/marketing/B7511CA2-CC50-4F2C-867D-DB15783CE3C5.jpg'; console.log(this.avatar.slice(0,5)) /* if(this.avatar.slice(0,5)=='https'){ }else{ this.avatar=this.avatar.replace('http','https'); } */ this.time=opt.time console.log(this.avatar) this.nickname=opt.name; if(opt.sellingPoint&&opt.sellingPoint!='undefined'){ this.sellingPoint=opt.sellingPoint; } console.log('this.sellingPoint==='+this.sellingPoint) //console.log(this.nickname+this.nickname.length) if(this.nickname.length>16){ this.nickname=this.nickname.substring(0,16)+'...' } if(opt.groupType!=0){ console.log(opt.groupType) this.groupType=opt.groupType; if(this.nickname.length>12){ this.nickname=this.nickname.substring(0,12)+'...' } } //console.log(this.nickname+this.nickname.length) this.userInfo=this.$store.state.userInfo; this.ext=this.$common.getExtStoreId(); this.canvasW =uni.upx2px(600) if(this.sellingPoint){ this.canvasH = uni.upx2px(840) }else{ this.canvasH = uni.upx2px(740) } var that=this; var type=opt.type if(type==2){ var bizType=2; var path='pages/activity/jkDetail' }else{ var bizType=1; var path='pages/shop/goodsDetail' } uni.showLoading({ title: '加载中' }) this.$request.httpBinary('openMall/shareQrCode', { bizType:bizType, path:path,//?id+this.id+'&shareId='+this.userInfo.openId, goodsId:opt.id, openId:this.userInfo.openId, unionId:this.ext.unionId },'GET').then(res => { //console.log(res) this.mpWxQr3=res; uni.hideLoading(); //this.mpWxQr2= 'data:image/png;base64,'+uni.arrayBufferToBase64(res) // this.mpWxQr4= uni.arrayBufferToBase64(res) this.toDrawCanvas() }) // this.$request.httpBinary('openMall/shareQrCode', { // bizType:1, // path:'pages/shop/goodsDetail',//?id+this.id+'&shareId='+this.userInfo.openId, // goodsId:opt.id, // openId:this.userInfo.openId, // unionId:this.ext.unionId // },'GET').then(res => { // //console.log(res) // this.mpWxQr2= 'data:image/png;base64,'+uni.arrayBufferToBase64(res) // // let theNode=uni.createSelectorQuery().select(".wcl") // // theNode.boundingClientRect((data)=>{ // // console.log(data) // // // that.mpWxQr=data // // }).exec() // // this.mpWxQr = uni.createSelectorQuery().select('wcl') // this.toDrawCanvas() // }) //return false; }, methods: { toSaveImage() { if (!this.finished) { uni.showToast({ title: '正在生成图片,稍后再试', icon: 'none' }) return } const that = this uni.canvasToTempFilePath({ canvasId: 'mini_poster', success: (res) => { uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: () => { uni.showToast({ title: '保存成功' }) }, fail() { uni.showToast({ icon: 'none', title: '保存名片码失败' }) } }) }, fail() { uni.showToast({ icon: 'none', title: '保存名片码失败' }) } }) }, async toDrawCanvas() { const padding = uni.upx2px(34) const cardHeight = uni.upx2px(420) const cw = this.canvasW - 2 * padding const r = uni.upx2px(12) let ctx = uni.createCanvasContext('mini_poster', this) // 左上角 var cx = uni.upx2px(30) var cy = uni.upx2px(30) //this._drawRoundRect(ctx, 30, 30, this.canvasW, this.canvasH, r) // ctx.arc(this.canvasW, 0, this.canvasW,this.canvasH, cx) // 透明背景 ctx.setFillStyle('rgba(255, 255, 255, 0)') //ctx.setFillStyle('#FFFFFF') //ctx.setFillStyle('#D53533') ctx.fillRect(0, 0, this.canvasW, this.canvasH) // draw card round rect this.drawback(ctx) this.drawRoundRect(ctx, padding, padding, cw, cardHeight, r, 2) // draw card content this.drawCard(ctx, padding, padding, cw, cardHeight) // draw avatar const av = uni.upx2px(540) const topimgh = uni.upx2px(360) //const topimgh ='auto' //console.log(av) //console.log(topimgh) const hi = await this.downloadImage(this.avatar) if (hi.tempFilePath) { const x = uni.upx2px(30) const y = uni.upx2px(30) this.drawRoundRectAvatar(ctx, x, y, av, topimgh, r, hi.tempFilePath) } if(this.groupType){ var ptw=uni.upx2px(60) var pth=uni.upx2px(32) var ptIcon=await this.downloadImage(this.ptImg); if (ptIcon.tempFilePath) { const x = uni.upx2px(30) const y = uni.upx2px(370) this.drawRoundRectAvatar(ctx, x, y, ptw, pth, r, ptIcon.tempFilePath) } } // draw hello info //this.drawHelloInfo(ctx, padding, padding + cardHeight + padding, cw) // draw qr code if (this.mpWxQr) { var fsm = uni.getFileSystemManager(); //var filePath='../../static/timg/CS.png' var times = new Date().getTime(); var codeimg = wx.env.USER_DATA_PATH + '/' + times + '.png'; var that=this; fsm.writeFile({ filePath: codeimg, // 要写入的文件路径 (本地路径) data: this.mpWxQr3, // 要写入的文本或二进制数据 encoding:"base64", // 指定写入文件的字符编码 success(e) { console.log(e) console.log(codeimg) var wxsx=uni.upx2px(48) if(that.sellingPoint){ var wxsy=uni.upx2px(649) }else{ var wxsy=uni.upx2px(549) } var wxwidth=uni.upx2px(158) ctx.drawImage(codeimg, wxsx, wxsy, wxwidth,wxwidth) }, fail(err) { console.log(err) } }); const hello = await this.downloadImage(this.mpWxQr) //const padding = uni.upx2px(34) //const av = uni.upx2px(180) //const totalH = this.calculateCanvasHeight() //console.log("totalH=="+totalH) //console.log(hello.tempFilePath) // var wxsx=uni.upx2px(68) // var wxsy=uni.upx2px(649) // var wxwidth=uni.upx2px(148) // ctx.drawImage(codeimg, wxsx, wxsy, wxwidth,wxwidth) if (hello.tempFilePath) { //ctx.drawImage(hello.tempFilePath, wxsx, wxsy, wxwidth,wxwidth) } } ctx.draw() this.finished = true }, async drawCard(ctx, x, y, w, h) { // draw company //let vp = y + uni.upx2px(45) //const hp = x + uni.upx2px(52) let vp = uni.upx2px(440) var hp = uni.upx2px(36) ctx.setTextBaseline('center') const fz30 = uni.upx2px(32) ctx.fillStyle = '#212121' ctx.setFontSize(fz30) if(this.groupType){ var namehp = uni.upx2px(100) ctx.fillText(this.nickname, namehp, vp) }else{ ctx.fillText(this.nickname, hp, vp) } var timeX=hp; var timeY=vp+20 const fz26 = uni.upx2px(26) ctx.setFillStyle('#3C3C3C') ctx.setFontSize(fz26) ctx.fillText(this.time, timeX, timeY) var sm=this.sellingPoint ctx.setFillStyle('#999999') ctx.setFontSize(fz26) var smy=timeY+20 var maxwidth = uni.upx2px(550) if(sm.length>20){ var sm1=sm.substring(0,20) ctx.fillText(sm1, timeX, smy) if(sm.length>40){ var sm2=sm.substring(20,40) ctx.fillText(sm2, timeX, smy+20) var sm3=sm.substring(40,60) ctx.fillText(sm3, timeX, smy+40) }else{ var sm2=sm.substring(20,40) ctx.fillText(sm2, timeX, smy+20) } }else{ ctx.fillText(sm, timeX, smy) } var wemtis1='名额有限 先到先得' var wemtisx=uni.upx2px(240) if(this.sellingPoint){ var wemtisy=uni.upx2px(700) }else{ var wemtisy=uni.upx2px(600) } ctx.setFillStyle('#999999') const fz24 = uni.upx2px(24) ctx.setFontSize(fz24) ctx.fillText(wemtis1,wemtisx,wemtisy) var wemtis2='长按二维码识别参与活动' var wemtisy2=wemtisy+30 ctx.fillText(wemtis2,wemtisx,wemtisy2) // draw nickname vp = vp + 30 vp = vp + 42 const iconW = uni.upx2px(30) const textH = hp + iconW + 6 ctx.setFillStyle('#333333') ctx.setFontSize(fz30) vp = vp + 28 ctx.setFillStyle('#333333') ctx.setFontSize(fz30) // ctx.fillText(this.showInvestAreas, textH, vp) const oPadding = uni.upx2px(34) const iPadding = uni.upx2px(40) const textW = w - textH + oPadding - iPadding //this.drawTextInOneLine(ctx, this.showInvestAreas, textH, vp, textW) vp = vp + 28 ctx.setFillStyle('#333333') ctx.setFontSize(fz30) //ctx.fillText(this.phone ? this.phone : '', textH, vp) }, async drawHelloInfo(ctx, x, y, w) { let vp = y + 12 const hp = x ctx.setTextBaseline('top') const fz30 = uni.upx2px(30) ctx.setFillStyle('#333333') ctx.setFontSize(fz30) ctx.fillText('您好,', hp, vp) const text = "我是来自 " + this.company + ' 的投资人' + this.nickname const lines = this.drawTextInLines(ctx, text, hp, vp, w, 26) vp += 26 * lines + 26 ctx.fillText('这是我的名片,请惠存。', hp, vp) vp += 26 ctx.fillText('谢谢', hp, vp) vp += 26 vp += 40 ctx.setFillStyle('#F37231') ctx.fillRect(hp, vp, 20, 3) vp += 7 ctx.setFillStyle('#333333') const fz28 = uni.upx2px(28) ctx.setFontSize(fz28) ctx.fillText('长按识别二维码', hp, vp) vp += 20 const ttt = '在大天使中查看我的更多信息' ctx.fillText(ttt, hp, vp) }, calculateCanvasHeight() { // 400 is card height const ctx = uni.createCanvasContext('test_poster') const padding = uni.upx2px(34) const text = "我是来自 " + this.company + ' 的投资人' + this.nickname const rows = this.drawTextInLines(ctx, text, padding, 0, this.canvasW - 2 * padding, 26) const cardH = uni.upx2px(380) const h = padding * 2 + cardH + padding + 12 + 26 * 3 + rows * 26 return h + 90 }, _drawRoundRect(ctx, x, y, w, h, r) { ctx.beginPath() // 左上角 console.log("x="+x+'y='+y+'w='+w+'h='+h+'r='+r) ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5) //ctx.arc(0, 0, 15, Math.PI, Math.PI * 1.5) // 右上角 ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2) //ctx.arc(0, 0, 0, Math.PI, Math.PI * 1.5) // 右下角 ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5) // 左下角 ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI) ctx.closePath() // ctx.strokeStyle = '#D8D8D8'; ctx.fillStyle = '#FFFFFF'; // ctx.stroke() ctx.fill() }, drawRoundRect(ctx, x, y, w, h, r, lineWidth) { //return false; ctx.save() //this._drawRoundRect(ctx, x, y, w, h, r) ctx.clip() // draw left border ctx.fillStyle = '#EEEEEE' if(this.sellingPoint){ var y=uni.upx2px(619) }else{ var y=uni.upx2px(519) } ctx.arc(0, 0, 15, Math.PI, Math.PI * 1.5) var bWidth=uni.upx2px(600) ctx.fillRect(0, y, bWidth, 2) ctx.restore() }, drawback(ctx){ ctx.save() var bWidth=uni.upx2px(12) this._drawRoundRect(ctx, 0, 0, this.canvasW, this.canvasH,bWidth ) ctx.clip() // draw left border ctx.fillStyle = '#FFFFFF' var bWidth=uni.upx2px(600) ctx.fillRect(0, 0, bWidth, this.canvasH) ctx.restore() }, drawRoundRectAvatar(ctx, x, y, w, h, r, imgPath) { ctx.save() this._drawRoundRect(ctx, x, y, w, h, r) ctx.clip() ctx.drawImage(imgPath, x, y, w, h) ctx.restore() }, // TODO: measureText not works in App drawTextInLines(ctx, t, x, y, w, lineHeight) { const chr = t.split("") let temp = '' let row = [] for (let i = 0; i < chr.length; i++) { if (ctx.measureText(temp).width < w) { // } else { row.push(temp) temp = '' } temp += chr[i] } row.push(temp) for (const i in row) { // i + 1 will be 11, 21,... ctx.fillText(row[i], x, (y + (i * 1 + 1) * lineHeight)) } return row.length }, // TODO: measureText not works in app drawTextInOneLine(ctx, t, x, y, w) { const chr = t.split('') let temp = '' for (let i = 0; i < chr.length; i++) { if (ctx.measureText(temp + '...').width <= w) { temp += chr[i] } else { temp = temp.substring(0, temp.length - 1) temp += '...' break } } ctx.fillText(temp, x, y) }, downloadImage(url) { return new Promise((resolve, reject) => { uni.downloadFile({ url: url, success: (res) => { return resolve(res) }, fail: (err) => { return reject(err) } }) }) } } } </script> <style scoped> .box{ width: 100%; height: 100vh; background: url('http://dmsphoto.66km.com.cn/thFiles/83BDAB66-DD76-4F3A-92B3-F6AF0BA57A9E.png'); background-size: 100% 100%; } .downloadBtn{ width: 329rpx; height: 92rpx; background: url('http://dmsphoto.66km.com.cn/thFiles/A0CF4704-69A8-4DAC-8943-75F98D1349DD.png'); background-size: 100% 100%; line-height: 92rpx; text-align: center; font-size: 28rpx; font-family: PingFangSC-Medium, PingFang SC; font-weight: 500; color: #DC490A; margin: 0 auto; } </style>