近一段時間的主要精力一直在微信小程序的開發上,常規業務邏輯的難度不大,文檔和社區內容都比較豐富,沒有遇到太多技術難題,但咱們的需求中有比較大的一塊就是繪圖——經過 canvas
繪製圖片提供給用戶進行後續的操做,在這一過程當中踩了不少坑,在此及後續的文章中作逐一總結,供交流探討更優方案。前端
本文中主要探討的是關於圖片資源的繪製,常規的網絡圖片繪製沒有什麼困難,拿到圖片URL與寬高後與所需的位置信息,一併做爲參數調用drawImage
方法便可,但前兩天遇到了一個特殊的場景,服務端綜合考慮後沒法提供圖片的URL,只能將圖片進行Base64轉碼後返回給前端,繪圖只能經過drawImage
方法,而這個方法只能傳入圖片的資源地址,不接受Base64數據:canvas
CanvasContext.drawImage(string imageResource, number sx, number sy, number sWidth, number sHeight, number dx, number dy, number dWidth, number dHeight)
小程序
咱們一塊兒來分析一下imageResource
參數,這個指的是圖片的資源地址,資源既能夠指網絡圖片資源,亦能夠指本地的圖片資源,因此突破口正是在這裏——本地圖片資源地址。大體思路就是將Base64字符串轉成ArrayBuffer格式數據,而後寫入文件系統獲得本地的資源地址,進而就能夠調用上述方法進行繪製了。說到這裏,就不得不介紹一下小程序的文件系統了,這塊在咱們常規的業務開發中使用的場景很少,文件系統是小程序提供的一套以小程序和用戶維度隔離的存儲以及一套相應的管理接口。經過wx.getFileSystemManager()
能夠獲取到全局惟一的文件系統管理器,全部文件系統的管理操做經過 FileSystemManager
來調用。這裏所講的文件主要分爲兩大類:微信小程序
顯然,這裏咱們要用的是本地文件,在手機終端使用小程序時,會有一塊獨立的文件存儲區域,以用戶維度隔離,即同一臺手機,每一個微信用戶不能訪問到其餘登陸用的文件,同一個用戶不一樣appid之間的文件也不能互相訪問:緩存
{{協議名}}://文件路徑,其中協議名開發者工具中爲"http",而在手機端爲"xfile"
複製代碼
這裏還要拓展一下,本地文件還能夠細分爲三種,即bash
其中前兩種類型只能調用特定的接口產生,不能直接寫入內容,因此咱們要用的不是這兩種,而是第三種——本地用戶文件,這是在1.7.0版本中新增的能力,在本地提供了一個用戶文件目錄,能夠供開發者進行自由的讀寫操做,經過wx.env.USER_DATA_PATH
能夠得到這個目錄的路徑。舉個🌰微信
//在本地用戶文件目錄下建立一個文件 wd.txt,寫入內容 「豌豆公主前端研發」
const fs = wx.getFileSystemManager();
const filePath = `${wx.env.USER_DATA_PATH}/wd.txt`;
fs.writeFile({
filePath: filePath,
data: '豌豆公主前端研發',
encoding: 'utf8',
success() {
return filePath;
},
fail() {
return (new Error('ERROR_WRITE'));
},
});
複製代碼
這樣咱們實現繪製Base64圖片的關鍵點就解決了,還有一個小問題就是將Base64的字符串轉成ArrayBuffer格式的數據,這個就比較簡單了,有現成的API支持wx.base64ToArrayBuffer()
。網絡
綜上,小程序端繪製Base64圖片的實現方案就已經有了,廢話很少說,上代碼:app
const fs = wx.getFileSystemManager();
const FILE_BASE_NAME = 'tmp_base64imgsrc';
function base64ToSrc(base64Data, callback) {
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64Data) || [];
if (!format) {
return (new Error('ERROR_PARSE'));
}
const filePath = `${wx.env.USER_DATA_PATH}/${FILE_BASE_NAME+Date.parse(new Date())}.${format}`;
const buffer = wx.base64ToArrayBuffer(bodyData);
fs.writeFile({
filePath,
data: buffer,
encoding: 'binary',
success() {
callback(filePath);
},
fail() {
return (new Error('ERROR_WRITE'));
},
});
}
複製代碼
以上方案不必定是最優解,且當拋磚引玉,若是你們有更好的實現方案也歡迎隨時交流探討~工具
說了這麼多,這個功能究竟是什麼呢?這就是咱們前段時間剛剛推出的一個產品,基於微信小程序的社交電商,當前爲邀請制註冊,若是你們想體驗一下的話能夠私聊我微信(xysz1991)索取邀請碼,或者識別下方二維碼完成一個團購任務便可自動註冊爲集客,自購省錢,分享還能夠賺取佣金哦~