1 // 繪制海報 2 drawPoster() { 3 uni.showLoading({ 4 title:"海報生成中...", 5 mask:true 6 }) 7 let _this = this 8 _this.isShow = true // 控制canvas 顯示,必須顯示的狀態下,才可繪制 9 let info = uni.getSystemInfoSync() 10 const pixelRatio = info.pixelRatio // 屏幕像素密度 11 uni.getImageInfo({ 12 src: _this.poster, //_this_pupop.image 13 success(image) { 14 const canvasId = "guidePopop" 15 let ctx = uni.createCanvasContext(canvasId,_this) // 自定義組件中 一定要傳入 this ,這里一開始沒加,困惑很久,一定要寫一下 16 let ratio = _this.pupopWidth/image.width 17 let draw_h = image.height*ratio 18 _this.pupopHeight = draw_h 19 ctx.drawImage(image.path,0,0,uni.upx2px(_this.pupopWidth),uni.upx2px(draw_h)) // 海報背景圖。 unp2px 用戶進行像素轉換。 20 // 繪制頭像 21 uni.getImageInfo({ 22 src: _this.userInfo.avatarUrl, 23 success(res){ 24 const size = 76 25 const x = 36 26 const y = 36 27 const acr_r = size/2 28 const acr_x = x+acr_r 29 const acr_y = y+acr_r 30 const img_x = acr_x/2 31 const img_y = acr_y/2 32 const img_w = size 33 const img_h = img_w 34 ctx.save(); // 先保存狀態 已便於畫完圓再用 35 ctx.beginPath(); //開始繪制 36 //先畫個圓 37 ctx.arc(uni.upx2px(acr_x), uni.upx2px(acr_y),uni.upx2px(acr_r), 0, Math.PI * 2); 38 ctx.setFillStyle('#ffffff') 39 ctx.fill()//保證圖片無bug填充 40 ctx.clip();//畫了圓 再剪切 原始畫布中剪切任意形狀和尺寸。一旦剪切了某個區域,則所有之后的繪圖都會被限制在被剪切的區域內 41 ctx.drawImage(res.path,uni.upx2px(img_x),uni.upx2px(img_y),uni.upx2px(img_w),uni.upx2px(img_h)) // 頭像 42 ctx.restore(); 43 // 繪制 昵稱 44 ctx.save(); // 先保存狀態 已便於畫完圓再用 45 const text_size = 28 46 const text_x = x + img_w + 29 47 const text_y = 64 48 ctx.setFillStyle('#FFFFFF') 49 ctx.setTextBaseline('top') 50 ctx.setFontSize(uni.upx2px(text_size)) 51 ctx.fillText('Hi '+_this.userInfo.nickName, uni.upx2px(text_x), uni.upx2px(text_y)) 52 // 繪制 小程序碼 53 uni.getImageInfo({ 54 src: _this.inviteQR, 55 success(res){ 56 const size = 160 57 const img_x = _this.pupopWidth - size - x 58 const img_y = _this.pupopHeight - size - y 59 const img_w = size 60 const img_h = img_w 61 ctx.drawImage(res.path,uni.upx2px(img_x),uni.upx2px(img_y),uni.upx2px(img_w),uni.upx2px(img_h)) // 頭像 62 ctx.draw(false, () => { 63 uni.canvasToTempFilePath({ 64 width: _this.pupopWidth, 65 height: draw_h, 66 destWidth: _this.pupopWidth * pixelRatio, 67 destHeight: draw_h *pixelRatio, 68 canvasId: canvasId, 69 fileType: 'png', 70 quality:1, 71 success: function(res) { 72 _this.posterImg = res.tempFilePath 73 _this.showCloseBtn = true 74 console.log(_this.posterImg) 75 uni.hideLoading() 76 }, 77 fail(error) { 78 console.log('4',error) 79 _this.isShow = false 80 uni.showLoading({ 81 title:'生成海報失敗,請稍后重試', 82 mask:true 83 }) 84 uni.hideLoading() 85 } 86 },_this) 87 }) 88 }, 89 fail(error) { 90 console.log('3',error) 91 uni.showLoading({ 92 title:'生成海報失敗,請稍后重試', 93 mask:true 94 }) 95 _this.isShow = false 96 uni.hideLoading() 97 } 98 }) 99 }, 100 fail(error) { 101 console.log('2',error) 102 uni.showLoading({ 103 title:'生成海報失敗,請稍后重試', 104 mask:true 105 }) 106 _this.isShow = false 107 uni.hideLoading() 108 } 109 }) 110 }, 111 fail(error) { 112 console.log('1',error) 113 _this.isShow = false 114 uni.showLoading({ 115 title:'生成海報失敗,請稍后重試', 116 mask:true 117 }) 118 uni.hideLoading() 119 } 120 }); 121 },
122 savePhoto(filePath){ // 保存海報 123 124 checkForAuthorization('scope.writePhotosAlbum').then(()=>{ // 上一篇有提到 125 uni.saveImageToPhotosAlbum({ 126 filePath:filePath, 127 success: function () { 128 uni.hideLoading() 129 }, 130 fail: function(e){ 131 uni.hideLoading() 132 if(e.errMsg == "saveImageToPhotosAlbum:fail cancel"){ 133 uni.showToast({ 134 title:"已取消", 135 icon:"none" 136 }) 137 }else{ 138 uni.showToast({ 139 title:"保存失敗", 140 icon:"none" 141 }) 142 } 143 } 144 }) 145 }).catch((err)=>{ 146 console.log(err.errMsg) 147 uni.showToast({ 148 title:"保存失敗", 149 icon:"none" 150 }) 151 }) 152 },
這里只展示了主要的繪制代碼,繪制的海報圖如下圖,繪制內容已標記。背景 + 用戶頭像 + 用戶昵稱 + 小程序碼 ,
這個彈窗是自定義組件,
uni.createCanvasContext(canvasId,_this) // 自定義組件中 一定要傳入 this ,這里一開始沒加,困惑很久,一定要寫一下
uni.draw(boolean,()=>{},_this) // 自定義組件中 一定要傳入 this ,這里一開始沒加,困惑很久,一定要寫一下