微信小程序之生成朋友圈分享圖,了解一下?

分享圖.png

這里是 Geek 小程序的源碼,點(diǎn)擊查看 github 源碼

前言

  • 在開(kāi)發(fā)小程序的過(guò)程中,你是否有將頁(yè)面生成分享圖并引導(dǎo)用戶轉(zhuǎn)發(fā)至朋友圈的需求?有,那就進(jìn)來(lái)看看,應(yīng)該是你想要的結(jié)果。

  • 在分享上,就目前來(lái)說(shuō),小程序是不能直接分享到朋友圈的,微信官方只開(kāi)放了分享到好友和群聊的 API。對(duì)于分享到朋友圈,現(xiàn)在大多數(shù)小程序所采用的方式,就是根據(jù)不同的需求生成一張帶小程序碼的圖片引導(dǎo)用戶分享至朋友圈。

  • 當(dāng)然分享圖也可以在后臺(tái)生成,但是你懂得,基本沒(méi)有那個(gè)后臺(tái)大哥愿意為你去用代碼寫(xiě)一張圖出來(lái),所以,咱們還是自給自足,??。

歡迎大家使用微信掃描【組件庫(kù)小程序碼】(或者微信直接搜索組件庫(kù)演示)查看運(yùn)行效果

組件庫(kù)演示小程序.png

生成分享圖大致流程如下~

image.png

官方文檔

關(guān)于生成二維碼

  • 微信官方獲取二維碼 API
  • 如果每一次分享的二維碼不同,需要要生成 帶參數(shù)的二維碼 (采用接口B)
  • 生成的二維碼需要下載到本地
  • 別忘了在 小程序微信公眾平臺(tái)后臺(tái) - 設(shè)置 - 開(kāi)發(fā)設(shè)置 - 服務(wù)器域名 - downloadFile 合法域名 中添加域名

1. 使用 canvas 進(jìn)行繪制

我們知道小程序是支持將 canvas 直接轉(zhuǎn)換為圖片的,我們可以充分利用這個(gè)先決條件

1.1 拿到設(shè)計(jì)的效果圖,我們可以先按標(biāo)注計(jì)算出每個(gè)元素的寬高以及在畫(huà)布中的位置,建議使用 百分比,這樣可以對(duì)所有的屏幕大小進(jìn)行適配

示例代碼如下:

const temp = 0.01;
//圖片長(zhǎng)寬比
const scale = 1.78;
//背景圖高度
const bgScale = 0.5;
//頭像和寬的比
const avatarWidthScale = 0.368;
const avatarHeightScale = 0.117;
//頭像白色圓形背景
const avatarBgWidthScale = 0.38;
const avatarStrokeWidth = 4;
//昵稱高度比
const nicknameHeightScale = 0.34 + 5 * temp;
//第一行文字高度
const topTextScale = 0.515 + 3 * temp;
//分享內(nèi)容
const contentScale = 0.585 + 3 * temp;
const contentScale2 = 0.620 + 3 * temp;
//二維碼直徑
const qrCodeWidthScale = 0.341;
//二維碼高度
const qrCodeHeightScale = 0.69;
//極客文字
const bpbScale = 0.91 + temp * 2;
//識(shí)別文字
const decodeScale = 0.935 + temp * 2;

1.2 涉及到圖片繪制

  • 本地圖片可以直接繪制
  • 如果要繪制的元素中含有網(wǎng)絡(luò)圖片,需要先將圖片下載到本地,不然在真機(jī)上無(wú)法顯示(親測(cè)在模擬器上可以繪制,但在 iPhone6s 真機(jī)上無(wú)法顯示)
  • 貼上頭像下載代碼:
/**
   * 下載頭像
   */
  downloadAvatar: function () {
    var that = this;
    wx.downloadFile({
      url: that.data.avatar,
      success: function (res) {
        that.setData({
          avatarPath: res.tempFilePath
        })
        that.drawImage();
      },
      fail: function () {
        that.showErrorModel();
      }
    })
  },

1.3 對(duì)各個(gè)元素進(jìn)行繪制

  • 對(duì)于文字過(guò)長(zhǎng)省略...,目前沒(méi)有好的辦法,暫時(shí)采用的是設(shè)置最大文字長(zhǎng)度,超出截?cái)啵⑹謩?dòng)添加....
  • 對(duì)于生成圓形頭像,可參考例子實(shí)現(xiàn)
drawImage: function () {
    var that = this;
    const ctx = wx.createCanvasContext('myCanvas', this);
    var bgPath = '../../image/share-bg.png';
    //設(shè)置 canvas 背景,不然生成的圖片背景會(huì)有黑色底
    ctx.setFillStyle(WHITE);
    ctx.fillRect(0, 0, windowWidth, windowHeight);

    //繪制背景圖片
    ctx.drawImage(bgPath, 0, 0, windowWidth, windowHeight * bgScale);

    //頭像背景圓
    ctx.arc(windowWidth / 2, avatarWidthScale / 2 * windowWidth + avatarHeightScale * windowHeight, (avatarWidthScale / 2) * windowWidth + avatarStrokeWidth, 0, 2 * Math.PI);
    ctx.setFillStyle(WHITE);
    ctx.fill();

    //先繪制圓,裁剪成圓形圖片
    ctx.save();
    ctx.beginPath();
    //圓的原點(diǎn)x坐標(biāo),y坐標(biāo),半徑,起始弧度,終止弧度
    ctx.arc(windowWidth / 2, avatarWidthScale / 2 * windowWidth + avatarHeightScale * windowHeight, (avatarWidthScale / 2) * windowWidth, 0, 2 * Math.PI);
    ctx.setStrokeStyle(WHITE);
    ctx.stroke();
    ctx.clip();
    //繪制頭像
    //圖片路徑,左上角x坐標(biāo),左上角y坐標(biāo),寬,高
    var avatarWidth = avatarWidthScale * windowWidth;//頭像半徑
    ctx.drawImage(that.data.avatarPath, windowWidth * (0.5 - avatarWidthScale / 2), avatarHeightScale * windowHeight, avatarWidth, avatarWidth);
    ctx.restore();

    //繪制 content
    ctx.setFillStyle(GRAY_COLOR);
    ctx.setFontSize(18);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.content, windowWidth / 2, contentScale * windowHeight);
    ctx.setFillStyle(GRAY_COLOR);
    ctx.setFontSize(18);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.contentOther, windowWidth / 2, contentScale2 * windowHeight);

    //繪制二維碼
    ctx.drawImage(that.data.QRPath, windowWidth * (0.5 - qrCodeWidthScale / 2), qrCodeHeightScale * windowHeight, qrCodeWidthScale * windowWidth, qrCodeWidthScale * windowWidth);
    console.log('font------------>' + wx.canIUse('canvasContext.font'));

    //繪制 按壓提示文字
    ctx.setFillStyle(TINT_COLOR);
    ctx.setFontSize(14);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.clickToMini, windowWidth / 2, decodeScale * windowHeight);

    //繪制加粗文字--------------------------------------------------------------
    //繪制昵稱
    that.setFontStyle(ctx, 'bold');
    ctx.setFillStyle(WHITE);
    ctx.setFontSize(20);
    ctx.setTextAlign('center');
    ctx.fillText(stringUtil.substringStr(that.data.nickname), windowWidth / 2, nicknameHeightScale * windowHeight);

    //繪制文字
    ctx.setFillStyle(THEME_COLOR);
    ctx.setFontSize(24);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.tip, windowWidth / 2, topTextScale * windowHeight);

    //繪制 Geek小程序
    ctx.setFillStyle(TINT_COLOR);
    ctx.setFontSize(16);
    ctx.setTextAlign('center');
    ctx.fillText(that.data.detailStr.bpbMini, windowWidth / 2, bpbScale * windowHeight);

    //繪制到 canvas 上
    ctx.draw(false, function () {
      console.log('callback--------------->');
      that.saveCanvasImage();
    });
  }

1.4 兼容處理

  • 一些 API 屬性是在高版本才有的,比如 文字加粗(基礎(chǔ)庫(kù) 1.9.90 開(kāi)始支持,低版本需做兼容處理
  • 在使用之前用 wx.canIUse 判斷
/**
   * 改變字體樣式
   */
  setFontStyle: function (ctx, fontWeight) {
    if (wx.canIUse('canvasContext.font')) {
      ctx.font = 'normal ' + fontWeight + ' ' + '14px' + ' sans-serif';
    }
  },

1.5 不同機(jī)型適配

  • 可以拿主流的幾款手機(jī)適配,包括 ios 和 Android,沒(méi)有問(wèn)題的話,就可以進(jìn)行下一步了

2. 調(diào)整樣式

  • 達(dá)到效果后修改 wxml 以及 wxss ,對(duì) canvas 的樣式調(diào)整
  • 確保 canvas 在屏幕可可顯示區(qū)域外,因?yàn)?canvas 的層級(jí)是最高的,我們直接在上面顯示圖片是不能顯示的,也不建議這么做(可以使用 cover-view
  • 這個(gè)自由發(fā)揮,可以將 canvas 的 position 設(shè)置為脫離文檔流(fixed),只要 canvas 不在屏幕顯示范圍即可,確保離可見(jiàn)區(qū)域足夠遠(yuǎn)
.canvas {
  width: 100%;
  position: fixed;
  top: 9999rpx;
  left: 0;
}

3. 將 canvas 保存為圖片

  • 這是最后一步,給用戶展示分享圖片的同時(shí),用戶可以選擇保存圖片到手機(jī)相冊(cè)

3.1 注意處理用戶授權(quán)問(wèn)題

  • 同時(shí)處理到用戶同意和拒絕權(quán)限

  //轉(zhuǎn)化為圖片
  saveCanvasImage: function () {
    var that = this;
    wx.canvasToTempFilePath({
      canvasId: 'myCanvas',
      success: function (res) {
        console.log(res.tempFilePath);
        that.setData({
          targetSharePath: res.tempFilePath,
          realShow: true
        })
      },
      complete: function () {
        that.hideLoading();
      }
    }, this)
  },

  /**
   * 保存到相冊(cè)
   */
  saveImageTap: function () {
    var that = this;
    that.requestAlbumScope();
  },


  /**
   * 檢測(cè)相冊(cè)權(quán)限
   */
  requestAlbumScope: function () {
    var that = this;
    // 獲取用戶信息
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.writePhotosAlbum']) {
          // 已經(jīng)授權(quán),可以直接調(diào)用 getUserInfo 獲取頭像昵稱,不會(huì)彈框
          that.saveImageToPhotosAlbum();
        } else {
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success(res) {
              that.saveImageToPhotosAlbum();
            },
            fail() {
              wx.showModal({
                title: '提示',
                content: '你需要授權(quán)才能保存圖片到相冊(cè)',
                success: function (res) {
                  if (res.confirm) {
                    wx.openSetting({
                      success: function (res) {
                        if (res.authSetting['scope.writePhotosAlbum']) {
                          that.saveImageToPhotosAlbum();
                        } else {
                          console.log('用戶未同意獲取用戶信息權(quán)限-------->success');
                        }
                      },
                      fail: function () {
                        console.log('用戶未同意獲取用戶信息權(quán)限-------->fail');
                      }
                    })
                  }
                }
              })
            }
          })
        }
      }
    })
  },

3.2 保存圖片到相冊(cè)


  saveImageToPhotosAlbum: function () {
    var that = this;
    wx.saveImageToPhotosAlbum({
      filePath: that.data.targetSharePath,
      success: function () {
        wx.showModal({
          title: '',
          content: '??圖片保存成功,\n快去分享到朋友圈吧',
          showCancel: false
        })
        that.hideDialog();
      }
    })
  },
  • 下面我將講解小程序自定義組件,以及對(duì)保存相冊(cè)的封裝,畢竟分享的地方會(huì)很多,封裝成組件會(huì)大大簡(jiǎn)化我們的代碼量以及工作量,這樣就可以少加點(diǎn)班,哈哈

歡迎關(guān)注 stone 的簡(jiǎn)書(shū)!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容