小程序生成分享圖片

小程序生成分享圖片

DevTools上的動圖效果

Canvas結構組成

從上面截圖能夠看出,canvas的主體組成部分包括:javascript

  1. 背景圖css

  2. 微信頭像和暱稱信息html

  3. 小程序碼(小程序碼會攜帶分享者的信息)java

須要注意的問題

經過小程序提供的畫布,咱們能很容易的完成上面的整個海報的繪製。可是,canvas的繪製都是基於像素(px)級別的,可是在小程序中,咱們的預覽圖和最終生成的圖,都須要根據機型進行適配。git

代碼實現

  1. 底部彈出的模態框
    模態框的實現見下面的XML內容,能夠看出具體組成以下:github

  2. canvas外面套了一個modals,主要目的是讓預覽圖看起來在DOM的最上面canvas

  3. shareCanvas就是咱們要繪製全部內容的畫布小程序

  4. modals-cancel-black是一層半透明的蒙層,儘可能將頁面的其它元素遮蓋到它的下面api

  5. 其次就是一個關閉按鈕和相應的文字說明微信

<!-- 分享圖 -->
  <view class="modals" hidden="{{isCanvasHidden}}">
    <canvas canvas-id="shareCanvas" class="share-canvas" style="width:680rpx;height:1000rpx" hidden="{{isCanvasHidden}}"></canvas>
    <view class="modals-cancel-black"></view>
    <view class="cancal-canvas-container" bindtap="hideCanvas">
      <image src="http://lc-adna4hf0.cn-n1.lcfile.com/13cb9cd1d79bbed4a47c.png" class="cancel-button"></image>
    </view>
    <view class="save-album-wrapper text-center">圖片已保存到相冊,可分享給好友</view>
  </view>
複製代碼
.modals {
  position: fixed;
  z-index: 999;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.modals-cancel-black {
  position: absolute;
  z-index: 1000;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, .8);
}
複製代碼
  1. 繪製canvas

從動圖能夠發現,canvas的繪製是從點擊底部模態框的「生成分享圖」就開始了

drawShareCanvas: function () {
    // 1.計算相對比例rpx
    // 2.根據rpx繪製背景圖片
    // 3.根據rpx繪製微信用戶信息部分
    // 4.根據rpx繪製小程序碼部分
}
複製代碼

上述的1-4的步驟之間,可能存在具體的前後關係,能夠根據本身的狀況來定製前後順序

  1. rpx計算方法

wx.getSystemInfo的返回值中能夠獲得移動端屏幕的具體寬度,小程序WXSS是以rpx做爲衡量單位,咱們的canvas寬高都是以rpx計算的寬高。可是canvas繪製時以px爲單位繪製。那麼咱們須要計算當前設備相對於375px的倍數。
後續的全部關於座標、長寬或者距離都須要乘以這個rpx倍數,才能達到適配全部倍數。

var rpx = 1
wx.getSystemInfo({
  success (res) {        
    rpx = res.windowWidth / 375
    // ...
  }
})
複製代碼
  1. 繪製背景

由於背景圖稍微比較大,在繪製時,經過ctx.scale()方法將畫布總體都縮放了0.5倍

wx.showLoading({
  title: '繪製背景圖'
})
wx.getImageInfo({
  src: 'http://lc-adna4hf0.cn-n1.lcfile.com/33111f0ba3409c8fdef9.png',
  success (res) {
    // 隱藏背景圖loading
    wx.hideLoading()
    const ctx = wx.createCanvasContext('shareCanvas')

    // 繪製背景圖
    ctx.scale(0.5, 0.5)
    ctx.drawImage(res.path, 0, 0, 680 * rpx, 1000 * rpx)
    ctx.stroke()

    // 繪製其它
  },
  fail () {
    wx.showToast({
      title: '背景圖獲取失敗',
      icon: 'none'
    })
  }
})
複製代碼
  1. 微信用戶信息

微信我的圖像須要繪製成圓形的,能夠用CanvasContext.arc(...)來繪製一個圓弧實現。圓弧會有默認的黑色邊框。清除邊框使用ctx.setLineWidth(0)。若是須要自定義邊框顏色,可使用ctx.setStrokeStyle('red')來設定。
   未指定ctx.clip()時,圖片不會被裁剪,看到的圖片仍是正方形。經過不指定裁剪的方式(註釋ctx.clip),能夠來精確肯定圖像的開始點的位置。圖像的開始繪製點位置爲:圓心橫座標 - 圓弧的半徑 = point - radius

let userinfo = wx.getStorageSync('userinfo')
if (userinfo) {
  wx.showLoading({
    title: '繪製用戶信息',
  })
  // 繪製我的信息部分
  wx.getImageInfo({
    src: userinfo.avatarUrl,
    success (avatar) {
      // 隱藏用戶信息loading
      wx.hideLoading()
	  let radius = 50 * rpx
	  let point = 70 * rpx

      ctx.scale(1, 1)
      ctx.save()
      ctx.beginPath()
      ctx.setLineWidth(0)
      ctx.arc(point, point, radius, 0, 2 * Math.PI)
      ctx.setLineWidth(0)
      ctx.closePath()                  
      ctx.save()
      ctx.clip()
      ctx.drawImage(avatar.path, (point - radius), (point - radius), 100 * rpx, 100 * rpx)
      ctx.restore()
	},
	fail (err) {
      wx.showToast({
        title: '獲取用戶頭像失敗',
        icon: 'none'
      })
	}
  })

  // 暱稱
  ctx.setFontSize(32 * rpx)
  ctx.setFillStyle('white')
  ctx.fillText(userinfo.nickName, 140 * rpx, 60 * rpx)
  ctx.stroke()
							
  // 稱謂
  ctx.setFontSize(24 * rpx)
  ctx.setFillStyle('#FEFEFE')
  ctx.fillText('尚德學習大使', 140 * rpx, 100 * rpx)
  ctx.stroke()
}
複製代碼
  1. 繪製小程序碼
    小程序碼由於會攜帶分享着信息,須要經過調用後臺接口來動態生成,因此是異步的。能夠在生成期間loading給用戶返回進度。獲得小程序碼的url地址後,就能夠根據前面的繪製方法,找到小程序碼的位置繪製便可。

  2. 保存到系統相冊

全部繪製步驟完成後,此時還剩兩個事情是待作的。1、保存canvas畫布內容到系統相冊;2、顯示預覽圖。
根據整張圖的製做順序,小程序碼是最後一步完成的,因此小程序碼繪製到canvas後,算是全部繪製動做完成,須要執行

ctx.draw()
// 下一步?=> 保存圖片到相冊
saveAlbum()
// 顯示預覽圖
that.setData({
    isCanvasHidden: false
})
複製代碼

按照上面的方式,咱們執行saveAlbum後發現,在開發工具上,每次都能正常的彈出保存圖片。可是在真機上測試時,偶爾會發現預覽圖已經出來了,可是到系統相冊查看,卻發現沒有生成想要的圖片。
經過查看小程序開發文檔才知道,wx.canvasToTempFilePath方法須要在ctx.draw的回調中執行(文檔地址)。因此,實際得這麼幹,畢竟人家定義接口的是大爺(嘻嘻)。

ctx.stroke()

ctx.draw(false, () => {
  that.saveAlbum()
})
// 這個段也能夠放第四行以後
that.setData({
  isCanvasHidden: false
})
複製代碼

保存到相冊的相關代碼

saveAlbum() {
    var that = this
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      canvasId: 'shareCanvas',
      success: function (res) {
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(saveRes) {
            wx.showToast({
              title: '保存成功',
              icon: 'success'
            })
          },
          fail() {
            wx.showToast({
              title: '保存失敗',
              icon: 'none'
            })
            that.hideCanvas()
          }
        })
      }
    })
  }
複製代碼

手機端效果展現

不支持mp4預覽,轉換成gif太大了。
WeChat_20181031180605.mp4

參考文檔

小程序Canvas API: developers.weixin.qq.com/miniprogram…

本篇文章由一文多發平臺ArtiPub自動發佈

相關文章
相關標籤/搜索