小程式匯出朋友圈海報詳細記錄

woodccc發表於2018-09-16

小程式提供了轉發給好友的介面,但是沒提供分享到朋友圈的介面。於是,只有引導使用者儲存圖片分享到朋友圈。 兩種方案:用微信 api 手動儲存,用 painter

微信 api

使用原生介面的話,大致是使用 canvas 繪製出海報,然後下載。所以重點是繪製出海報,下載的流程都是一樣的。當然在儲存圖片到相簿前,還會需要獲取儲存圖片到相簿的許可權。總結下來就是canvas繪製,獲取儲存許可權,儲存圖片這三個步驟。 首先來看繪製海報,需要使用以下介面

  • wx.createCanvasContext 建立 canvas context
  • ctx.drawImage 繪製圖片到 canvas
  • ctx.fillText 寫文字
  • wx.getImageInfo 獲取網路圖片的 tempFilePath
  • ctx.draw canvas 繪製

最終儲存下來的海報是這樣的

wx816dc6e826dcc6b5.o6zAJs298QQbQgcF7A5dTg_F9y2s.S7bTLz7u0Rbr691154e07805442dba9bccedfcf52c3d.png

繪製的內容很簡單,首先就是背景圖;然後是分享者的頭像;接下來是 @ xx 邀請你 這樣一個文字描述;最後就是底部的小程式碼。

首先,建立 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))
複製程式碼

這裡會將原始尺寸和繪製的尺寸等比例轉換一下,就不贅述了。再接下來就是繪製小程式碼了。由於小程式碼是帶了分享者的資訊,所以必須是臨時獲取的網路圖片資源,具體怎麼獲取帶有分享者資訊的小程式碼,會專門寫一篇文章介紹。

繪製圖片

繪製頭像與小程式碼,這兩張圖片都是網路資源,所以都要使用 wx. getImageInfo 介面將其下載下來放到微信記憶體中,然後使用其response.path 繪製。小程式並不支援直接的繪製網路圖片,而且也不支援 base64圖片的繪製(雖然模擬器上會有效果)。頭像的繪製還有有一個裁剪圓形頭像的過程。wx.getImageInfo是非同步的,所以在回撥函式裡繪製,當然這不是好的方式。可以使用 promise 來解決,由於現在已經不用這個程式碼了,就沒有去改了。

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()
                })
              }
            })
          }
        })
複製程式碼

到這一步,繪製基本就結束了。我們所要的海報內容已經可以在 canvas 上呈現了,接下來就是將 canvas 的內容儲存為圖片了。值得提醒的是,ctx.draw這個介面也是非同步的,需要在其回撥中執行下載的操作。

獲取 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 儲存一張分享朋友圈的海報就好了。

painter

painter 是什麼呢?

小程式生成圖片庫,輕鬆通過 json 方式繪製一張可以發到朋友圈的圖片

painter 是酷家樂開源的小程式圖片生成庫,類似 echarts,使用配置物件渲染圖片到 canvas。渲染完成後回撥會返回 tempFilePath,然後呼叫 wx.saveImageToPhotosAlbum 即可儲存。儲存的步驟和第一種方案一致,關鍵是獲取到 tempFilePath。

按照其 readme 來操作就好了,由於專案是使用了 mpvue,所以使用了mpvue接入方案

使用 painter

        <painter v-if="showPainter" class='canvas' @imgOK="onImgOk" :palette="palette"/>
複製程式碼

為什麼要使用 v-if 呢,需要在所有資料都準備好了後再渲染 painter,否則會無限繪製。

data() {
  return {
    //painter 配置資料
    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 中。

注意

儲存海報難免會涉及到微信頭像。需要注意的是,直接傳入微信頭像可能會出現儲存出來的海報沒有頭像。究其原因,微信返回的頭像連結有兩種,一是https://wx.qlogo.cn,還有一種http://thirdwx.qlogo.cn。那麼問題來了,小程式配置的允許通訊的域名只能是 https。所以當出現 thirdwx.qlogo.cn 的頭像時,就會出現儲存海報沒有頭像。

那麼為什麼會有兩種頭像連結呢?

最後選擇的解決方案是,後端將頭像下載臨時儲存到伺服器,返回一個指向自己伺服器的連結,這樣域名就可以自己控制了。

總結

總結一下,遇到的一些坑

  • 小程式canvas不能支援 base64
  • drow 有回撥
  • drawImage 不能直接使用網路圖片
  • 需要處理獲取許可權,使用者拒絕後的場景

最後

海報就暴露了,是的,就是漫遊鯨。歡迎掃個碼體驗漫遊鯨小程式,歡迎瞭解下漫遊鯨。如果還不瞭解漫遊鯨,那麼點選就能瞭解漫遊鯨啦

wx816dc6e826dcc6b5.o6zAJs298QQbQgcF7A5dTg_F9y2s.S7bTLz7u0Rbr691154e07805442dba9bccedfcf52c3d.png

相關文章