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

分享圖.png

這里是 Geek 小程序的源碼涧郊,點擊查看 github 源碼

前言

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

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

  • 當然分享圖也可以在后臺生成搬卒,但是你懂得,基本沒有那個后臺大哥愿意為你去用代碼寫一張圖出來翎卓,所以契邀,咱們還是自給自足,??失暴。

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

組件庫演示小程序.png

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

image.png

官方文檔

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

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

1. 使用 canvas 進行繪制

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

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

示例代碼如下:

const temp = 0.01;
//圖片長寬比
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;
//識別文字
const decodeScale = 0.935 + temp * 2;

1.2 涉及到圖片繪制

  • 本地圖片可以直接繪制
  • 如果要繪制的元素中含有網(wǎng)絡(luò)圖片矩肩,需要先將圖片下載到本地现恼,不然在真機上無法顯示(親測在模擬器上可以繪制,但在 iPhone6s 真機上無法顯示)
  • 貼上頭像下載代碼:
/**
   * 下載頭像
   */
  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 對各個元素進行繪制

  • 對于文字過長省略...黍檩,目前沒有好的辦法叉袍,暫時采用的是設(shè)置最大文字長度,超出截斷刽酱,并手動添加....
  • 對于生成圓形頭像喳逛,可參考例子實現(xiàn)
drawImage: function () {
    var that = this;
    const ctx = wx.createCanvasContext('myCanvas', this);
    var bgPath = '../../image/share-bg.png';
    //設(shè)置 canvas 背景,不然生成的圖片背景會有黑色底
    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();
    //圓的原點x坐標润文,y坐標姐呐,半徑,起始弧度典蝌,終止弧度
    ctx.arc(windowWidth / 2, avatarWidthScale / 2 * windowWidth + avatarHeightScale * windowHeight, (avatarWidthScale / 2) * windowWidth, 0, 2 * Math.PI);
    ctx.setStrokeStyle(WHITE);
    ctx.stroke();
    ctx.clip();
    //繪制頭像
    //圖片路徑曙砂,左上角x坐標,左上角y坐標骏掀,寬麦轰,高
    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ǔ)庫 1.9.90 開始支持砖织,低版本需做兼容處理
  • 在使用之前用 wx.canIUse 判斷
/**
   * 改變字體樣式
   */
  setFontStyle: function (ctx, fontWeight) {
    if (wx.canIUse('canvasContext.font')) {
      ctx.font = 'normal ' + fontWeight + ' ' + '14px' + ' sans-serif';
    }
  },

1.5 不同機型適配

  • 可以拿主流的幾款手機適配款侵,包括 ios 和 Android,沒有問題的話侧纯,就可以進行下一步了

2. 調(diào)整樣式

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

3. 將 canvas 保存為圖片

  • 這是最后一步,給用戶展示分享圖片的同時贸弥,用戶可以選擇保存圖片到手機相冊

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

  • 同時處理到用戶同意和拒絕權(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)
  },

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


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


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

歡迎關(guān)注 stone 的簡書问慎!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末萍摊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蝴乔,更是在濱河造成了極大的恐慌记餐,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薇正,死亡現(xiàn)場離奇詭異片酝,居然都是意外死亡,警方通過查閱死者的電腦和手機挖腰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門雕沿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人猴仑,你說我怎么就攤上這事审轮。” “怎么了辽俗?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵疾渣,是天一觀的道長。 經(jīng)常有香客問我崖飘,道長榴捡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任朱浴,我火速辦了婚禮吊圾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翰蠢。我一直安慰自己项乒,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布梁沧。 她就那樣靜靜地躺著檀何,像睡著了一般。 火紅的嫁衣襯著肌膚如雪廷支。 梳的紋絲不亂的頭發(fā)上埃碱,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音酥泞,去河邊找鬼砚殿。 笑死,一個胖子當著我的面吹牛芝囤,可吹牛的內(nèi)容都是我干的似炎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼悯姊,長吁一口氣:“原來是場噩夢啊……” “哼羡藐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悯许,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤仆嗦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后先壕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘩扼,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡谆甜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了集绰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片规辱。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖栽燕,靈堂內(nèi)的尸體忽然破棺而出罕袋,到底是詐尸還是另有隱情,我是刑警寧澤碍岔,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布浴讯,位于F島的核電站,受9級特大地震影響蔼啦,放射性物質(zhì)發(fā)生泄漏榆纽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一询吴、第九天 我趴在偏房一處隱蔽的房頂上張望掠河。 院中可真熱鬧,春花似錦猛计、人聲如沸唠摹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勾拉。三九已至,卻和暖如春盗温,著一層夾襖步出監(jiān)牢的瞬間藕赞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工卖局, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斧蜕,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓砚偶,卻偏偏與公主長得像批销,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子染坯,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容