項目功能整理:微信小程序生成二維碼海報

剛作完一個微信小程序的項目,如今對項目裏的一些功能進行整理,這篇文章記錄下如何在小程序裏實現生成帶有二維碼的海報,並保存到用戶相冊。html

以此文章記錄,便於後續項目使用。vue

項目是基於mpvue作的。canvas

項目要求

每一個用戶能夠生成一個屬於本身的推廣二維碼,拉新後記錄推廣人。小程序

生成的海報最終效果也不復雜,如圖:微信小程序

下面保存圖片是個白底的按鈕,跟背景色混一塊就看不到了。。。

需求分析

經過查閱微信小程序的文檔得知,能夠藉助於小程序提供的canvas繪圖功能根據設計圖來繪製個canvas圖,而後經過保存圖片到相冊這個API把圖片保存到用戶的手機相冊。api

海報中有些內容是固定不變的,好比背景圖、邀請話術以及下面長按圖片的提示語,而還有些內容是動態的,好比用戶名和小程序碼,不一樣項目需求不同,但都會有變更和不變兩類內容,而後咱們根據設計圖一點一點把內容繪製到圖上就行啦。bash

知道要作什麼了,那麼咱們來羅列下要作的事情(吉德林法則有云:把要解決的問題清清楚楚的列下來,問題就解決了一半)微信

  • 獲取用戶名
  • 獲取用戶專屬小程序碼
  • 圖片繪製
  • 處理用戶取消保存到相冊的受權

動手實現

  1. 首先在頁面裏插入個canvas標籤,並把它的位置調整到界面外。至於爲啥是經過控制位置而不是控制顯示隱藏,動手試過的兄弟都應該知道,優先級問題。
<canvas class="cv-ct-canvas" canvas-id="cv-pic"></canvas>

.cv-ct-canvas {
  position: absolute;
  left: 800rpx;
  width: 300px;
  height: 500px;
}
複製代碼
  1. 準備用戶名、小程序碼。由於我這裏的背景圖也是個遠程圖片,因此也一併要先下載。
const { tempFilePath: bg } = await this.downloadFile('$(STATICFILE_URL)/prom-share-bg.png')
let name = this.userInfo.NickName;
// 下載圖片到本地
const { tempFilePath } = await this.downloadFile(this.qrcodeUrl);
複製代碼

這裏要說明下,這個downloadFile方法是把微信的downloadFile方法進行了同步處理,其實很簡單,就是用個Promise包裹一下。async

  1. 往畫布上逐個繪製。
const ctx = wx.createCanvasContext("cv-pic");
// 填充背景色
ctx.setFillStyle("#f8f8f8");
ctx.fillRect(0, 0, 300, 400);
ctx.fill();
ctx.setFillStyle("#ffffff");
ctx.fillRect(0, 400, 300, 100);
ctx.fill();
// 填充背景圖
ctx.drawImage(bg, 30, 20, 240, 365);
// 寫入名字
ctx.setFontSize(15);
ctx.setFillStyle("#FFF9F0");
ctx.fillText(name, 61, 300);
// 寫兩行提示
ctx.setFillStyle("#322F30");
ctx.setFontSize(14);
ctx.fillText("長按識別小程序碼", 33, 440);
ctx.fillText("超值禮包等你來搶", 33, 465);
// 填充小程序碼
ctx.drawImage(tempFilePath, 0, 0, 280, 280, 200, 410, 80, 80);
const that = this;
// 把canvas圖保存到臨時目錄
ctx.draw(false, function() {
  wx.canvasToTempFilePath({
    canvasId: "cv-pic",
    success(res) {
      let url = res.tempFilePath;
      that.savePic = url;
    }
  });
});
複製代碼

在最後用canvasToTempFilePath把圖片先保存到了臨時目錄,並把臨時目錄的地址賦值給了savePic,由於界面上要展現這個圖,因此在界面上會有個Image標籤,這個標籤的地址就是savePic。函數

  1. 保存到用戶相冊,代碼比較簡單,直接上:
if (!this.savePic) return;
  const that = this;
  wx.saveImageToPhotosAlbum({
    filePath: this.savePic,
    success: function() {
      that.showSaveCode = false;
      wx.showToast({
        title: "保存成功",
        icon: "success",
        duration: 2000
      });
    },
    fail: function () {
      that.getWriteToAlbumSetting()
    }
  });
複製代碼

對於最後這個fail裏面的getWriteToAlbumSetting方法,下面做解釋。

  1. 處理用戶拒絕受權。對於須要用戶受權的操做,咱們如今是這麼處理的:
  • 先在頁面data裏聲明一個變量表示當前用戶是否已經受權了,好比這裏我聲明瞭canWriteToAlbum用來表示是否能夠保存圖片到相冊。
  • 而後在頁面加載時,如在mounted鉤子函數裏執行一次getWriteToAlbumSetting這個方法,該方法主要是經過wx.getSetting獲取當前用戶是否已經受權,代碼以下:
async getWriteToAlbumSetting() {
  // this.getSetting 方法也是對wx.getSetting的一個同步封裝處理
  let status = await this.getSetting('writePhotosAlbum')
  // 由於用戶第一次進行操做的時候,受權狀態爲undefined,只有在明確拒絕過的時候纔會是false
  if (status === true || status === undefined) {
    this.canWriteToAlbum = true
  } else {
    this.canWriteToAlbum = false
  }
}
複製代碼
  • 在頁面中,根據用戶的受權狀況,顯示表面相同其實不一樣的操做按鈕:
<div class="cv-save" @click="saveToPhotosAlbum" v-if="canWriteToAlbum">保存圖片</div>
<div class="cv-save" @click="openAlbumSetting" v-else>保存圖片</div>
複製代碼

至於爲何要這麼作,固然仍是由於小程序的限制啦。若是用戶拒絕過受權,再次點擊保存按鈕,要彈出受權界面,而微信明確要求,彈出受權界面必須是用戶直接點擊按鈕觸發,因此只能這樣實現了。openAlbumSetting代碼以下:

async openAlbumSetting() {
  // 仍是對微信API的同步封裝
  let status = await this.openSetting('writePhotosAlbum')
  // false表示又拒絕了
  if (status === false) return
  // 只有明確受權了才進行保存到相冊的操做
  this.canWriteToAlbum = true
  this.saveToPhotosAlbum()
}
複製代碼

總結

這篇文章除了記錄對於生成分享海報的實現外,主要還說明了如何處理用戶拒絕受權的狀況,這裏雖然只說了對於拒絕保存圖片的受權,但對於其餘操做的受權拒絕處理也能夠這樣。

第一次寫文章,有點亂,之後慢慢練習吧~~~

相關文章
相關標籤/搜索