微信小程序使用canvas實現生成海報圖的功能


最近開發中要實現一個需求,用戶點擊分享生成一個圖片海報,可以供用戶發朋友圈或者其他使用(感覺沒人會用~),用到了小程序canvas,和web上的功能基本一樣,記錄一下。---還沒上線一周,這個功能就被撤了

首先預設幾個工具函數

 

1/小程序開發使用的是 rpx,但是canvas里的單位使用的 px ,就需要轉換設計圖的尺寸

// 單位轉換 const rpx2px = rpx => deviceWidth / 750 * rpx 

其中deviceWidth就是設備的寬度,可以通過wx.getSystemInfo()獲取到,即windowWidth

 

2、獲取網絡圖片的信息

// 獲取圖片信息 const getImageInfo = url => { return new Promise((resolve, reject) => { wx.getImageInfo({ src: url, success: resolve, fail: reject, }) }) } 

需要注意的是需要添加downloadFile的合法域名

資源搜索網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com

3、文本換行

/** * 設置文本行數,超出省略 * @param {object} ctx canvas實例 * @param {string} text 文本數據 * @param {number} lineNum 行數 * @param {number} width 文字寬度最寬默認 620rpx * 返回 由每一行組成的數組 */ const setTextLine = (ctx, text, lineNum = 1, width = 610) => { const str_arr = String(text).split('') width = rpx2px(width) let temp = '' // 分行 let row_arr = str_arr.reduce((arr, word) => { const w = ctx.measureText(temp).width if (w < width) { temp += word; } else { arr.push(temp) temp = word } return arr }, []) row_arr.push(temp) temp = '' // 判斷需要的行數 row_arr = row_arr.slice(0,lineNum) if (row_arr.length > 1){ // 最后一行超出則省略號 row_arr[row_arr.length - 1].split().every(v => { temp += v if (ctx.measureText(temp).width > (width - 20)) { temp += '...' return false } return true }) // row_arr.pop() // row_arr.push(temp) row_arr.splice(row_arr.length - 1, 1, temp) } return row_arr } 

這里就是借助ctx.measureText()來獲取文本的寬度,看是否會超出canvas的寬度,然后根據傳參來控制行數,原理就是給最后一行的內容添加省略號即可,函數里我沒有判斷僅需一行但是超出一行的情況,因為我們是允許2行的,所以不需要判斷,有需要可以自行添加

接下來就可以執行繪制過程了,首先如果我們有用到網絡圖片。則需要在圖片下載到本地后開始,

...
const url1 = getImageInfo(url1)
const url2 = getImageInfo(url2) Promise.all([product_img]).then(([url1, url2]) => { ... }) ... 

這里就是用到了promise,不熟的可以看這里promise

在Promise.all中獲取canvas

...
const ctx = wx.createCanvasContext('myCanvas', this) // 繪制背景 const canvas_W = rpx2px(705) const canvas_H = rpx2px(1180) ctx.setFillStyle('#fff') ctx.fillRect(0, 0, canvas_W, canvas_H) ... 

繪制背景的目的是防止生成的圖片無內容區域透明,當然有特殊需求的可以不 接下來的繪制圖片的話,使用的ctx.drawImage()這個API,傳入圖片的左上角坐標和寬高即可,示例:

// 繪制logo const logo_SX = rpx2px(35) const logo_SY = rpx2px(23) const logo_W = rpx2px(253) const logo_H = rpx2px(80) ctx.drawImage('/images/logo.png', logo_SX, logo_SY, logo_W, logo_H) 

繪制文本時,如果文本長度不確定,使用上述封裝的函數處理文本內容,超出添加省略號即可,使用ctx.fillText()繪制

全部繪制完成之后,調用ctx.draw(cb)將之前在繪圖上下文中的描述(路徑、變形、樣式)畫到 canvas 中。 如果不操作生成圖片,到這一步就結束了,需要生成圖片操作的,在回調函數中進行操作即可

ctx.draw(false, () => { wx.canvasToTempFilePath({ canvasId: 'myCanvas', quality: 1, success: result => { ...something } }, this) }) 

把當前畫布指定區域的內容導出生成指定大小的圖片。在 draw() 回調里調用該方法才能保證圖片導出成功. 這里的quality是對jpg格式圖片的壓縮范圍,0-1之間的值,web上使用canvas,在toDataURL的第二個參數,可以實現壓縮圖片(jpg/webp)

圖片保存到手機:

wx.saveImageToPhotosAlbum({
      filePath: result.tempFilePath, success: res1 => { app.showTips(0, '圖片已保存') }, fail: err => { app.showTips(0, '圖片生成失敗') } }) 

到這里圖片保存完成,但是實際使用中,該功能需要使用用戶的相冊權限,如果用戶拒絕了授權,在下次調用的時候,就會直接失敗 所以需要給用戶一個友好的提示,即使用wx.getSetting獲取用戶授權情況,如果用戶拒絕過授權,則提示用戶進入設置頁面手動進行授權


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM