作者:小白
轉發連結:https://segmentfault.com/a/1190000019083548
項目需求寫完有一段時間了,但是還是想回過來總結一下,一是對項目的回顧優化等,二是對坑的地方做個記錄,避免以後遇到類似的問題。
利用微信強大的社交能力通過小程序達到裂變的目的,拉取新用戶。
生成的海報如下
1、利用小程序官方提供的api可以直接分享轉發到微信群打開小程序
2、利用小程序生成海報保存圖片到相冊分享到朋友圈,用戶長按識別二維碼關注公眾號或者打開小程序來達到裂變的目的
相信大家應該都會有類似的迷惑,就是如何按照產品設計的那樣繪製成海報,其實當時我也是不知道如何下手,認真想了下得通過canvas繪製成圖片,這樣用戶保存這個圖片到相冊,就可以分享到朋友圈了。但是要繪製的圖片上面不僅有文字還有數字、圖片、二維碼等且都是活的,這個要怎麼動態生成呢。認真想了下,需要一點一點的將文字和數字,背景圖繪製到畫布上去,這樣通過api最終合成一個圖片導出到手機相冊中。
1、二維碼的動態獲取和繪製(包括如何生成小程序二維碼、公眾號二維碼、打開網頁二維碼)
2、背景圖如何繪製,獲取圖片信息
3、將繪製完成的圖片保存到本地相冊
4、處理用戶是否取消授權保存到相冊
這裡我具體寫下圍繞上面所提出的問題,描述大概實現的過程
①首先創建canvas畫布,我把畫布定位設成負的,是為了不讓它顯示在頁面上,是因為我嘗試把canvas通過判斷條件動態的顯示和隱藏,在繪製的時候會出現問題,所以採用了這種方法,這裡還有一定要設置畫布的大小。
<canvas canvas-id=&34; style=&34;></canvas>
②創建好畫布之後,先繪製背景圖,因為背景圖我是放在本地,所以獲取 <canvas> 組件 canvas-id 屬性,通過createCanvasContext創建canvas的繪圖上下文 CanvasContext 對象。使用drawImage繪製圖像到畫布,第一個參數是圖片的本地地址,後面兩個參數是圖像相對畫布左上角位置的x軸和y軸,最後兩個參數是設置圖像的寬高。
const ctx = wx.createCanvasContext(&39;)ctx.drawImage(&39;, 0, 0, 690, 1085)
③創建好背景圖後,在背景圖上繪製頭像,文字和數字。通過getImageInfo獲取頭像的信息,這裡需要注意下在獲取的網絡圖片要先配置download域名才能生效,具體在小程序後臺設置裡配置。
獲取頭像地址,首先量取頭像在畫布中的大小,和x軸Y軸的坐標,這裡的result[0]是我用promise封裝返回的一個圖片地址
let headImg = new Promise(function (resolve) { wx.getImageInfo({ src: `${app.globalData.baseUrl2}${that.data.currentChildren.headImg}`, success: function (res) { resolve(res.path) }, fail: function (err) { console.log(err) wx.showToast({ title: &39;, icon: &39; }) } }) }) let avatarurl_width = 60, //繪製的頭像寬度 avatarurl_heigth = 60, //繪製的頭像高度 avatarurl_x = 28, //繪製的頭像在畫布上的位置 avatarurl_y = 36; //繪製的頭像在畫布上的位置 ctx.save(); // 先保存狀態 已便於畫完圓再用 ctx.beginPath(); //開始繪製 //先畫個圓 前兩個參數確定了圓心 (x,y) 坐標 第三個參數是圓的半徑 四參數是繪圖方向 默認是false,即順時針 ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false); ctx.clip(); //畫了圓 再剪切 原始畫布中剪切任意形狀和尺寸。一旦剪切了某個區域,則所有之後的繪圖都會被限制在被剪切的區域內 ctx.drawImage(result[0], avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推進去圖片
這裡舉個例子說下如何繪製文字,比如我要繪製如下這個「字」,需要動態獲取前面字數的總寬度,這樣才能設置「字」的x軸坐標,這裡我本來是想通過measureText來測量字體的寬度,但是在iOS端第一次獲取的寬度值不對,關於這個問題,我還在微信開發者社區提了bug,所以我想用另一個方法來實現,就是先獲取正常情況下一個字的寬度值,然後乘以總字數就獲得了總寬度,親試是可以的。
let allReading = 97 / 6 / app.globalData.ratio * wordNumber.toString().length + 325;ctx.font = &39;;ctx.setFillStyle(&ffffff&39;字&39;小程序碼的本地地址&39;myCanvas&39;繪製成功&39;繪製失敗&34;scope.writePhotosAlbum&39;圖片保存成功,快去分享到朋友圈吧~&39;none&39;保存失敗&39;none&39;scope.writePhotosAlbum&39;scope.writePhotosAlbum&39;圖片保存成功,快去分享到朋友圈吧~&39;none&39;保存失敗&39;none&39;請設置允許訪問相冊&39;請設置允許訪問相冊&39;none&39;圖片保存成功,快去分享到朋友圈吧~&39;none&39;保存失敗&39;none' }) } }) } }, fail(err) { console.log(err) } }) }
至此所有的步驟都已實現,在繪製的時候會遇到一些異步請求後臺返回的數據,所以我用promise和async和await進行了封裝,確保導出的圖片信息是完整的。在繪製的過程確實遇到一些坑的地方。比如初開始導出的圖片比例大小不對,還有用measureText測量文字寬度不對,多次繪製(可能受網絡原因)有時導出的圖片上的文字顏色會有誤差等。如果你也遇到一些比較坑的地方可以一起探討下做個記錄
- END -
作者:小白
轉發連結:https://segmentfault.com/a/1190000019083548