從上面截圖能夠看出,canvas的主體組成部分包括:javascript
經過小程序提供的畫布,咱們能很容易的完成上面的整個海報的繪製。可是,canvas的繪製都是基於像素(px)級別的,可是在小程序中,咱們的預覽圖和最終生成的圖,都須要根據機型進行適配。css
底部彈出的模態框
模態框的實現見下面的XML內容,能夠看出具體組成以下:html
<!-- 分享圖 --> <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); }
從動圖能夠發現,canvas的繪製是從點擊底部模態框的「生成分享圖」就開始了java
drawShareCanvas: function () { // 1.計算相對比例rpx // 2.根據rpx繪製背景圖片 // 3.根據rpx繪製微信用戶信息部分 // 4.根據rpx繪製小程序碼部分 }
上述的1-4的步驟之間,可能存在具體的前後關係,能夠根據本身的狀況來定製前後順序
git
wx.getSystemInfo的返回值中能夠獲得移動端屏幕的具體寬度,小程序WXSS是以rpx做爲衡量單位,咱們的canvas寬高都是以rpx計算的寬高。可是canvas繪製時以px爲單位繪製。那麼咱們須要計算當前設備相對於375px的倍數。
後續的全部關於座標、長寬或者距離都須要乘以這個rpx倍數,才能達到適配全部倍數。github
var rpx = 1 wx.getSystemInfo({ success (res) { rpx = res.windowWidth / 375 // ... } })
由於背景圖稍微比較大,在繪製時,經過ctx.scale()方法將畫布總體都縮放了0.5倍canvas
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' }) } })
微信我的圖像須要繪製成圓形的,能夠用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、保存canvas畫布內容到系統相冊;2、顯示預覽圖。
根據整張圖的製做順序,小程序碼是最後一步完成的,因此小程序碼繪製到canvas後,算是全部繪製動做完成,須要執行api
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: https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.html
本篇文章由一文多發平臺ArtiPub自動發佈