近一段时间的主要精力一直在微信小程序的开发上,常规业务逻辑的难度不大,文档和社区内容都比较丰富,没有遇到太多技术难题,但咱们的需求中有比较大的一块就是绘图——经过 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)索取邀请码,或者识别下方二维码完成一个团购任务便可自动注册为集客,自购省钱,分享还能够赚取佣金哦~