小程序導出朋友圈海報詳細記錄
小程序提供了轉發(fā)給好友的接口,但是沒提供分享到朋友圈的接口。于是,只有引導用戶保存圖片分享到朋友圈。 兩種方案:用微信 api 手動保存,用 painter 。
微信 api使用原生接口的話,大致是使用 canvas 繪制出海報,然后下載。所以重點是繪制出海報,下載的流程都是一樣的。當然在保存圖片到相冊前,還會需要獲取保存圖片到相冊的權限??偨Y下來就是canvas繪制,獲取保存權限,保存圖片這三個步驟。 首先來看繪制海報,需要使用以下接口
- wx.createCanvasContext 創(chuàng)建 canvas context
- ctx.drawImage 繪制圖片到 canvas
- ctx.fillText 寫文字
- wx.getImageInfo 獲取網(wǎng)絡圖片的 tempFilePath
- ctx.draw canvas 繪制
繪制的內容很簡單,首先就是背景圖;然后是分享者的頭像;接下來是 @ xx 邀請你 這樣一個文本描述;最后就是底部的小程序碼。
首先,創(chuàng)建 canvas 畫布<canvas canvas-id='canvas' class='canvas' :style="{height: windowHeight + 'px'}"/> 復制代碼
使用小程序 createCanvasContext api ,需要傳入 canvasid
const ctx = wx.createCanvasContext('canvas') 復制代碼
然后將背景圖片繪制出來,背景圖片是放在本地的圖片。
ctx.drawImage('../../../static/assets/img/poster_background.png', 0, 0, this.windowWidth, this.windowHeight) 復制代碼然后寫上文字
ctx.setFontSize(12); ctx.setFillStyle('#FFFFFF'); ctx.setTextAlign('center'); ctx.fillText(`${this.privateUserInfo.nickname} 邀您領取`, this.windowWidth / 2, this.transformScale(520)) 復制代碼
這里會將原始尺寸和繪制的尺寸等比例轉換一下,就不贅述了。再接下來就是繪制小程序碼了。由于小程序碼是帶了分享者的信息,所以必須是臨時獲取的網(wǎng)絡圖片資源,具體怎么獲取帶有分享者信息的小程序碼,會專門寫一篇文章介紹。
繪制圖片繪制頭像與小程序碼,這兩張圖片都是網(wǎng)絡資源,所以都要使用 wx. getImageInfo 接口將其下載下來放到微信內存中,然后使用其response.path 繪制。小程序并不支持直接的繪制網(wǎng)絡圖片,而且也不支持 base64圖片的繪制(雖然模擬器上會有效果)。頭像的繪制還有有一個裁剪圓形頭像的過程。wx.getImageInfo是異步的,所以在回調函數(shù)里繪制,當然這不是好的方式??梢允褂?promise 來解決,由于現(xiàn)在已經(jīng)不用這個代碼了,就沒有去改了。
wx.getImageInfo({ src: miniProgramCodeSrc, success: (response) => { const miniProgramCodeSize = this.transformScale(160) ctx.drawImage(response.path, this.transformScale(85), this.transformScale(710), miniProgramCodeSize, miniProgramCodeSize) wx.getImageInfo({ src: this.privateUserInfo.avatar, success: (response) => { const avatarSize = this.transformScale(100) //先繪制圓,裁剪成圓形圖片 ctx.save(); ctx.beginPath(); //圓的原點x坐標,y坐標,半徑,起始弧度,終止弧度 ctx.arc(this.transformScale(320), this.transformScale(425), avatarSize / 2, 0, 2 * Math.PI); ctx.setStrokeStyle('#ffffff'); ctx.stroke(); ctx.clip(); ctx.drawImage(response.path, this.transformScale(270), this.transformScale(375), avatarSize, avatarSize) ctx.restore(); ctx.draw(false, () => { this.saveToTempFilePath() }) } }) } }) 復制代碼
到這一步,繪制基本就結束了。我們所要的海報內容已經(jīng)可以在 canvas 上呈現(xiàn)了,接下來就是將 canvas 的內容保存為圖片了。值得提醒的是,ctx.draw這個接口也是異步的,需要在其回調中執(zhí)行下載的操作。
獲取 tempFilePath- wx.canvasToTempFilePath 獲取整個 canvas 的tempFilePath
保存圖片最重要的就是tempFilePath了,使用canvasToTempFilePath 獲取 tempFilePath。需要注意的是canvasToTempFilePath接口二參需要傳入 this。
saveToTempFilePath() { wx.canvasToTempFilePath({ canvasId: 'canvas', success: (response) => { //獲取相冊授權 } }, this) } 復制代碼
獲取 tempFilePath 成功后再獲取保存權限,當然也可以先獲取保存權限,再獲取tempFilePath。
獲取保存權限首先查看是否有保存權限,有權限就可以直接保存了。沒有權限就先獲取權限,再保存。
- wx.getSetting 查看權限列表
- wx.authorize 若沒有保存圖片權限,進行授權
wx.getSetting({ success: (res) => { if (!res.authSetting['scope.writePhotosAlbum']) { wx.authorize({ scope:'scope.writePhotosAlbum', success: () => { this.saveImageToPhotosAlbumByWX(response.tempFilePath) } }) } else { this.saveImageToPhotosAlbumByWX(response.tempFilePath) } } }) 復制代碼保存圖片到相冊
- wx.saveImageToPhotosAlbum 保存圖片到相冊
這一步就很簡單了,萬事俱備,只差保存了。調用 wx.saveImageToPhotosAlbum 即可。
saveImageToPhotosAlbumByWX(tempFilePath) { wx.saveImageToPhotosAlbum({ filePath: tempFilePath, complete: () => { // 其他操作 } }) } 復制代碼
到這里,使用原生 api 保存一張分享朋友圈的海報就好了。
painterpainter 是什么呢?
小程序生成圖片庫,輕松通過 json 方式繪制一張可以發(fā)到朋友圈的圖片
painter 是酷家樂開源的小程序圖片生成庫,類似 echarts,使用配置對象渲染圖片到 canvas。渲染完成后回調會返回 tempFilePath,然后調用 wx.saveImageToPhotosAlbum 即可保存。保存的步驟和第一種方案一致,關鍵是獲取到 tempFilePath。
按照其 readme 來操作就好了,由于項目是使用了 mpvue,所以使用了 mpvue接入方案 。
使用 painter<painter v-if="showPainter" class='canvas' @imgOK="onImgOk" :palette="palette"/> 復制代碼
為什么要使用 v-if 呢,需要在所有數(shù)據(jù)都準備好了后再渲染 painter,否則會無限繪制。
data() { return { //painter 配置數(shù)據(jù) palette: { width: '640rpx', height: '1008rpx', background: '/static/assets/img/poster_background.png', views: [ { type: 'image', url: '', css: { top: '380rpx', left: '320rpx', align: 'center', width: '100rpx', height: '100rpx', borderRadius: '50rpx' } }, { type: 'text', text: '', css: { top: '490rpx', left: '320rpx', align: 'center', fontSize: '24rpx', color: '#fff' } }, { type: 'image', url: '', css: { top: '690rpx', left: '85rpx', width: '180rpx', height: '180rpx' } } ] } } }, computed: { showPainter() { const avatar = this.palette.views[0].url const text = this.palette.views[1].text const qrCodeUrl = this.palette.views[2].url return avatar !== '' && text !== '' && qrCodeUrl!== '' } } 復制代碼
在 painter繪制成功的回調里,將 tempFilePath 保存起來。接下來的權限獲取和保存圖片到相冊流程就和上一個方案一致了。但是,需要提醒的是,tempFilePath 需要放在全局變量中,不能放在data 中。
總結總結一下,遇到的一些坑
- 小程序canvas不能支持 base64
- drow 有回調
- drawImage 不能直接使用網(wǎng)絡圖片
- 需要處理獲取權限,用戶拒絕后的場景
第二部分:如何開通一個小商店