微信小程序纯前端生成海报并保存本地
需求
公司開發微信小程序,有一個海報頁面,需要用戶點擊生成海報,可以將該該swipe-item 生成一個帶二維碼的圖片,最終由純前端實現!
技術調研
- 因為小程序的打包限制,不可能將所有的圖片都放在代碼目錄里面。所以就得使用遠端的圖片,但是因為canvas對跨域圖片的不支持,可以使用微信小程序中的API :wx.getImageInfo()現將遠端的圖片臨時保存。
- canvas 組件是由客戶端創建的原生組件,它的層級是最高的,不能通過 z-index 控制層級;并且使用display:none 和 visibility:hidden 的方式隱藏會導致canvas無法捕獲畫布內容,所以通過給canvas外部嵌套一個width:0;height:0;overflow:hidden的父級。
實現步驟
將遠端圖片暫存本地(以用戶頭像為例)
wx.getUserInfo({ //獲取微信用戶信息success: function (res) {this.getImageInfo(res.userInfo.avatarUrl); // 調取圖片處理方法this.setData({userName: res.userInfo.nickName});}}); getImageInfo(url){ // 圖片緩存本地的方法if(typeof url === 'string'){wx.getImageInfo({ // 小程序獲取圖片信息APIsrc: url,success: function (res) {this.setData({head_img:res.path})},fail(err) {console.log(err)}})}canvas繪制圖片
點擊生成海報按鈕
handlePoster(e){wx.getSetting({ // 獲取用戶設置success(res) {if (!res.authSetting['scope.writePhotosAlbum']) { // 如果用戶之前拒絕了授權wx.openSetting({success(tag){if (tag.authSetting["scope.writePhotosAlbum"]){ // 用戶在設置頁選擇同意授權// wx.showLoading({// title: '正在生成...',// })}}});}else{ // 用戶已經授權wx.showLoading({title: '正在生成...',})}}})此時頁面出現loading狀態,canvas開始繪制海報:
首先繪制整個底部背景
在這里,我暫且用本地圖片作為演示代替。繪制的canvas圖片大小為750px*1344px大小,最終生成格式為jpg。大小大概就200多kb。非常的小,清晰度也不錯。
我選擇的背景圖如上圖所示;
繪制海報的正文圖片
// 繪制圖片模板的 banner圖ctx.drawImage(arr2[1], 40,40, 670, 580);繪制時間
因為我們的海報上面的時間 xxxx.xx.xx中的每個數字和點都是圖片,所以時間也是一個個的小的以數字命名的圖片繪制上去。而后臺提供給我們的時間是個 秒(s)為單位的時間戳。首先得將時間戳轉換為一個時間數字組成的數組:
dateFilter(date){let gmt = new Date(date * 1000);let nYear=String(gmt.getFullYear());let nMonth =this.numFormatting(gmt.getMonth()+1);let nDay =this.numFormatting(gmt.getDate());let end_date = (nYear + '.' + nMonth + '.' + nDay).split("") ;return end_date},/*** 處理 月份 天數 個位數*/numFormatting(num){if(String(num).length<2){return '0'+num}else{return num}},假設處理好的時間格式為 :
let times=['2', '0', '1', '8', '.', '0', '4','.','1','2'];接下來是繪制時間:
// 繪制 圖片模板 的時間const TEXT_DATE = ['2', '0', '1', '8', '.', '0', '4','.','1','2'];for (let i = 0; i < TEXT_DATE.length; i++) {if (TEXT_DATE[i] != '.') {var path3 = `./${TEXT_DATE[i]}.png`;} else {var path3 = './point.png';}let clientx = 40 + 16 * i;ctx.drawImage(path3, clientx, 640, 16, 32);}繪制用戶頭像
因為二維碼中顯示的用戶頭像是一個圓形圖像,所以處理方式為:
// 繪制頭像ctx.save();let r=32;let d = r*2;let cx = 102;let cy = 1172;ctx.arc(cx+r, cy+r, r, 0, 2 * Math.PI);ctx.clip();ctx.drawImage(this.data.head_img, cx, cy, d, d);ctx.restore();這個時候 ,海報所需要的所有圖片已經繪制成功,接下來我們開始處理文字部分:
canvas 繪制文字
canvas并不會自動的將文字折行處理,所以我們得自己考慮每行顯示多少個文字,還得考慮中英文和符號所占字節的不同,在此,封裝一個處理方法:
textByteLength(text,num){ // text為傳入的文本 num為單行顯示的字節長度let strLength = 0; // text byte lengthlet 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] // [處理文字的總字節長度,每行顯示內容的數組,行數]},這個時候 就可以開始繪制文字了:
繪制正文和 出處
const CONTENT_ROW_LENGTH = 40; // 正文 單行顯示字符長度let [contentLeng, contentArray, contentRows] = this.textByteLength(this.data.nodesData[index].text, CONTENT_ROW_LENGTH);ctx.setTextAlign('left')ctx.setFontSize(32);let contentHh = 32 * 1.3;for (let m = 0; m < contentArray.length; m++) {ctx.fillText(contentArray[m], 40, 732 + contentHh * m);}// 繪制 出處ctx.setTextAlign('right')ctx.setFontSize(32);ctx.fillText(`——${this.data.nodesData[index].refer}`, 710, 996, 710);繪制二維碼邊上的說明
// 繪制二維碼右邊說明ctx.setTextAlign('left')ctx.setFontSize(28);ctx.setFillStyle('rgba(34,34,34,.64)')ctx.fillText('長按小程序碼', 250, 1174);ctx.fillText(`${this.data.userName}邀你進入掌閱讀好書`, 250, 1230);ctx.draw();此時如果canvas標簽能夠顯示查看,就能看到一個完美的海報繪制完成,現在只差最后一步,保存canvas;使用微信方法 canvasToTempFilePath()將canvas海報保存到本地臨時文件路徑;在使用saveImageToPhotosAlbum()將圖片保存到本地相冊:
setTimeout(function () {wx.canvasToTempFilePath({canvasId: 'notes',fileType:'jpg',success: function (res) {wx.saveImageToPhotosAlbum({filePath: res.tempFilePath,success(res) {wx.hideLoading();wx.showToast({title: '保存成功',});},fail(){wx.hideLoading()}})}})}, 500);然后查看存儲圖片的路徑文件夾,最終生成的海報:
總結:
在做這個功能之前,canvas用的非常少,很多方法都是現成百度查詢得出來的結果,這次的canvas生成海報并保存本地的實現過程中,讓我學到了很多東西;因為項目做得比較急,很多的代碼沒有經過細致的打磨,在此,也希望看到本文章的朋友們及時指點。
總結
以上是生活随笔為你收集整理的微信小程序纯前端生成海报并保存本地的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UG NX 10 草图之草图基准设
- 下一篇: 数据安全之MySQL数据加解密的实现方案