效果圖:
<view class='poste_box' id='canvas-container' style='opacity:{{opacity}}'> <canvas canvas-id="myCanvas" style="width:100%;height:900rpx;" /> <view class='wrapper_fuc'> <button style='background-color:#fff;' class='btnshare iconfont icon-guanyu' open-type='share'> 微信好友</button> <button style='background-color:#fff;' class='btn_item iconfont icon-guanyu' bindtap="saveShareImg"> 保存圖片</button> </view> </view> page{ background-color: #EDEEF2; background-image: url(https://www.cnblogs.com/images/cnblogs_com/520BigBear/1196074/t_dog.jpg); background-size: cover; background-position: center } .poste_box{ width: 85%; margin: auto; margin-top: 50rpx; background-color: #fff; border: 1rpx solid #ddd; box-shadow:0px 0px 10px 5px #D8D7DD; } .savePoste{ background-color: #FF8427; width: 90%; margin-left: auto; margin-right: auto; margin-top:30rpx; color: #fff; } .saveTitle{ font-size: 25rpx; color: #666; width: 90%; margin-left: auto; margin-right: auto; margin-top: 20rpx; text-align: center; } .wrapper_fuc{ display: flex; justify-content: space-between } //我在js中注釋的代碼很重要,實際開發中繪制商品海報必然是用網絡圖片,
但經過多次嘗試網絡圖片是不可以直接繪制在canvas畫布上的,就必須要把他緩存下來,弄一個本地路徑
wx.downloadFile
Page({ data: { opacity:0, cardInfo: { avater: "https://www.cnblogs.com/images/cnblogs_com/520BigBear/1196074/t_dog.jpg", //需要https圖片路徑 qrCode: "https://www.cnblogs.com/images/cnblogs_com/520BigBear/1196074/t_love.jpg", //需要https圖片路徑 TagText: "大熊", //標簽 Name: '大熊', //姓名 Position: "程序員鼓勵師", //職位 Mobile: "13888888888", //手機 Company: "熊野有限公司", //公司 } }, onLoad: function () { this.getAvaterInfo(); let that = this setTimeout(function () { that.setData({ opacity: 0.9 }); }, 1500); }, /** * 先下載頭像圖片 */ getAvaterInfo: function () { wx.showLoading({ title: '生成中...', mask: true, }); var that = this; wx.downloadFile({ url: that.data.cardInfo.avater, //頭像圖片路徑 success: function (res) { wx.hideLoading(); if (res.statusCode === 200) { var avaterSrc = res.tempFilePath; //下載成功返回結果 that.getQrCode(avaterSrc); //繼續下載二維碼圖片 } else { wx.showToast({ title: '頭像下載失敗!', icon: 'none', duration: 2000, success: function () { var avaterSrc = ""; that.getQrCode(avaterSrc); } }) } } }) }, /** * 下載二維碼圖片 */ getQrCode: function (avaterSrc) { wx.showLoading({ title: '生成中...', mask: true, }); var that = this; wx.downloadFile({ url: that.data.cardInfo.qrCode, //二維碼路徑 success: function (res) { wx.hideLoading(); if (res.statusCode === 200) { var codeSrc = res.tempFilePath; that.sharePosteCanvas(avaterSrc, codeSrc); } else { wx.showToast({ title: '二維碼下載失敗!', icon: 'none', duration: 2000, success: function () { var codeSrc = ""; that.sharePosteCanvas(avaterSrc, codeSrc); } }) } } }) }, /** * 開始用canvas繪制分享海報 * @param avaterSrc 下載的頭像圖片路徑 * @param codeSrc 下載的二維碼圖片路徑 */ sharePosteCanvas: function (avaterSrc, codeSrc) { wx.showLoading({ title: '生成中...', mask: true, }) var that = this; var cardInfo = that.data.cardInfo; //需要繪制的數據集合 const ctx = wx.createCanvasContext('myCanvas'); //創建畫布 var width = ""; wx.createSelectorQuery().select('#canvas-container').boundingClientRect(function (rect) { var height = rect.height; var right = rect.right; width = rect.width * 0.8; var left = rect.left + 5; ctx.setFillStyle('#fff'); ctx.fillRect(0, 0, rect.width, height); //頭像為正方形 if (avaterSrc) { ctx.drawImage(avaterSrc, left, 20, width, width); ctx.setFontSize(14); ctx.setFillStyle('#fff'); ctx.setTextAlign('left'); } //標簽 if (cardInfo.TagText) { ctx.fillText(cardInfo.TagText, left + 20, width - 4); const metrics = ctx.measureText(cardInfo.TagText); //測量文本信息 ctx.stroke(); ctx.rect(left + 10, width - 20, metrics.width + 20, 25); ctx.setFillStyle('rgba(255,255,255,0.4)'); ctx.fill(); } //姓名 if (cardInfo.Name) { ctx.setFontSize(14); ctx.setFillStyle('#000'); ctx.setTextAlign('left'); ctx.fillText(cardInfo.Name, left, width + 60); } //職位 if (cardInfo.Position) { ctx.setFontSize(12); ctx.setFillStyle('#666'); ctx.setTextAlign('left'); ctx.fillText(cardInfo.Position, left, width + 85); } //電話 if (cardInfo.Mobile) { ctx.setFontSize(12); ctx.setFillStyle('#666'); ctx.setTextAlign('left'); ctx.fillText(cardInfo.Mobile, left, width + 105); } // 公司名稱 if (cardInfo.Company) { const CONTENT_ROW_LENGTH = 24; // 正文 單行顯示字符長度 let [contentLeng, contentArray, contentRows] = that.textByteLength(cardInfo.Company, CONTENT_ROW_LENGTH); ctx.setTextAlign('left'); ctx.setFillStyle('#000'); ctx.setFontSize(10); let contentHh = 22 * 1; for (let m = 0; m < contentArray.length; m++) { ctx.fillText(contentArray[m], left, width + 150 + contentHh * m); } } // 繪制二維碼 if (codeSrc) { ctx.drawImage(codeSrc, left + 160, width + 40, width / 3, width / 3) ctx.setFontSize(10); ctx.setFillStyle('#000'); ctx.fillText("微信掃碼或長按識別", left + 160, width + 150); }
//畫個圓 頭部 圓圓圓圓圓圓圓圓圓圓圓圓圓圓圓圓圓圓圓圓圓
if (codeSrc) {
ctx.beginPath();
//ctx.arc(x,y,r,a,b,c) x:圓的x坐標, y:圓的y坐標, r:半徑 ;后面默認就行
ctx.arc(70, 70, 50, 0, 2 * Math.PI, false) //畫一個圓形裁剪區域
ctx.clip() //裁剪
// ctx.drawImage(codeSrc, '左右偏移量', '上下偏移', '寬', '長')
ctx.drawImage(codeSrc, 20, 20, width / 2, width / 2)
ctx.setStrokeStyle('rgba(0,0,0,0)') //防止黑圈 設置透明
ctx.stroke();
ctx.restore();
}
}).exec()
//注意一點的是保存圖片時需要延遲,這是老版的寫法,沒有啥問題,新版寫法可以通過draw回調畫圖成功后調用保存圖片的api wx.canvasToTempFilePath。這個時候就不需要寫延時保存圖片。
setTimeout(function () { ctx.draw(); wx.hideLoading(); }, 1000) }, /** * 多行文字處理,每行顯示數量 * @param text 為傳入的文本 * @param num 為單行顯示的字節長度 */ textByteLength(text, num) { let strLength = 0; // text byte length let rows = 1; let str = 0; let arr = []; for (let j = 0; j < text.length; j++) { if (text.charCodeAt(j) > 255) { strLength += 2; if (strLength > rows * num) { strLength++; arr.push(text.slice(str, j)); str = j; rows++; } } else { strLength++; if (strLength > rows * num) { arr.push(text.slice(str, j)); str = j; rows++; } } } arr.push(text.slice(str, text.length)); return [strLength, arr, rows] // [處理文字的總字節長度,每行顯示內容的數組,行數] }, //點擊保存到相冊 saveShareImg: function () { var that = this; wx.showLoading({ title: '正在保存', mask: true, }) setTimeout(function () { wx.canvasToTempFilePath({ canvasId: 'myCanvas', success: function (res) { wx.hideLoading(); var tempFilePath = res.tempFilePath; wx.saveImageToPhotosAlbum({ filePath: tempFilePath, success(res) { // utils.aiCardActionRecord(19); wx.showModal({ content: '保存成功!', showCancel: false, confirmText: '好的', confirmColor: '#333', success: function (res) { if (res.confirm) { } }, fail: function (res) { } }) }, fail: function (res) { wx.showToast({ title: res.errMsg, icon: 'none', duration: 2000 }) } }) } }); }, 1000); }, })
友情鏈接 資源參考 :https://blog.csdn.net/qq_41629498/article/details/82052729
https://www.jianshu.com/p/6204e9d9b277
資源共享,一起學習, 一起進步 ! peace & love