這是借用女神照生成的分享的海報,圖片來自網絡。
新增了poster組件和更新圖片自適應html
準備兩張圖片鏈接,最好是本身開發帳號驗證的https圖片連接。
其實就是canvas實現方式,首先要就是定義一個canvas容器,把容器放在中間,圖片也要動態計算大小居中,顯示下面的文字和二維碼也是要根據容器動態去改變,這就是大概的實現思路。
git
利用微信小程序canvas生成海報分享圖片,這個生成圖片排版和適配不一樣尺寸的手機是一個難點,特別是圖片適應問題,我處理的方法是動態獲取容器的寬度進行適應就是利用微信API wx.createSelectorQuery(),不知道還有沒有更好的辦法能夠請教。github
1.下載頭像
爲了確保圖片下載完成以後,再回調其它方法執行下一步。canvas
getAvaterInfo: function (cardInfo) {//cardInfo是傳入的信息參數,按實際須要。 wx.showLoading({ title: '生成中...',mask: true,}); var that = this; if (cardInfo.CardInfo.Avater) { wx.downloadFile({ url: '圖片路徑', success: function (res) { wx.hideLoading(); if (res.statusCode === 200) { var avaterSrc = res.tempFilePath; that.getQrCode(avaterSrc, cardInfo); }else{ wx.showToast({ title: '頭像下載失敗!', icon:'none', duration: 2000, success:function(){ that.getQrCode(avaterSrc = "", cardInfo);//回調另外一個圖片下載 } }) } } }) } else { wx.hideLoading(); that.getQrCode(avaterSrc = "", cardInfo);//回調另外一個圖片下載 } },
2.下載二維碼
二維碼下載同樣的道理,就是先下載完成,再進行繪圖。小程序
getQrCode: function (avaterSrc, cardInfo) { wx.showLoading({ title: '生成中...', mask: true, }); var that = this; if (cardInfo.CardInfo.QrCode) { wx.downloadFile({ url: cardInfo.CardInfo.QrCode, success: function (res) { wx.hideLoading(); if (res.statusCode === 200) { var codeSrc = res.tempFilePath; that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的繪圖方法 } else { wx.showToast({ title: '二維碼下載失敗!', icon: 'none', duration: 2000, success: function () { var codeSrc = ""; that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的繪圖方法 } }) } } }) } else { wx.hideLoading(); var codeSrc = ""; that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的繪圖方法 } },
3.繪製分享海報
這裏纔是canvas實現繪製的過程微信小程序
sharePosteCanvas: function (cardInfo, avaterSrc, codeSrc) { wx.showLoading({ title: '生成中...', mask: true, }) var that = this; 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.TagList.length > 0) { ctx.fillText(cardInfo.TagList[0].TagName, left + 20, width - 4); //標籤 const metrics = ctx.measureText(cardInfo.TagList[0].TagName); //測量文本信息 ctx.stroke(); ctx.rect(left + 10, width - 20, metrics.width + 40, 25); ctx.setFillStyle('rgba(255,255,255,0.4)'); ctx.fill(); } if (cardInfo.CardInfo.Name) { ctx.setFontSize(14); ctx.setFillStyle('#000'); ctx.setTextAlign('left'); ctx.fillText(cardInfo.CardInfo.Name, left, width + 60); //姓名 } if (cardInfo.CardInfo.Position) { ctx.setFontSize(12); ctx.setFillStyle('#666'); ctx.setTextAlign('left'); ctx.fillText(cardInfo.CardInfo.Position, left, width + 85); //職位 } if (cardInfo.CardInfo.Mobile) { ctx.setFontSize(12); ctx.setFillStyle('#666'); ctx.setTextAlign('left'); ctx.fillText(cardInfo.CardInfo.Mobile, left, width + 105); //電話 } if (cardInfo.CardInfo.Company) { // 公司名稱 const CONTENT_ROW_LENGTH = 24; // 正文 單行顯示字符長度 let [contentLeng, contentArray, contentRows] = that.textByteLength(cardInfo.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); } } // 繪製二維碼cardInfo.CardInfo.QrCode if (codeSrc) { ctx.drawImage(codeSrc, left + 150, width + 40, width / 3, width / 3) ctx.setFontSize(10); ctx.setFillStyle('#000'); ctx.setTextAlign('right'); ctx.fillText("微信掃碼或長按識別", left + 235, width + 150); } }).exec() setTimeout(function () { ctx.draw(); 這裏有個須要注意就是,這個方法是在繪製完成以後在調用,否則容易其它被覆蓋。 wx.hideLoading(); }, 1000) },
4.多行顯示文字
這個函數就是須要多行顯示文字的時候進行折行,就是切分爲數組。數組
textByteLength(text, num) { // 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] // [處理文字的總字節長度,每行顯示內容的數組,行數] },
5.保存繪製生成圖片
這一步就是最後把canvas生成圖片了,大功告成。微信
//點擊保存到相冊 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) { 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); },
1.圖片要提早下載
這裏面還有一個問題就是,圖片要提早下載完以後再繪圖,否則圖片顯示不出來,能夠把下載圖片的方法單獨拎出來,而後下載圖片後回調繪圖方法。網絡
這樣就大功告成了,有問題能夠和聯繫做者,一塊兒進步。
喜歡就點點喜歡鼓勵
DEMO路徑:https://github.com/kingbuwu/poster
demo上封裝了poster組件和顯示頭圖圖片自適應ide