最近在开发“生成小程序码”功能,由于小程序canvas组件在真机中无法渲染base64格式的图片,所以使用writeFile方法在客户端创建图片的思路实现。
但发现,如果图片名字是一样的话,尽管“小程序码接口”每次返回的ArrayBuffer数据不一样,安卓机还是会出现图片不更新的情况。于是思路变成,创建一个目录,每次在这个目录下生成随机名字的图片,为避免造成缓存过大,每次生成图片前都清空目录。
以下代码中使用了开发者文档中的一个二维码,所以存在跨越问题,请勾选
js代码
const dir = wx.env.USER_DATA_PATH + '/test';
Page({
data: {
codeSrc: ''
},
onLoad: function (options) {
this.createPhoto();
},
createPhoto() {
Promise.all([
this.getCodeBuffer(),//获取小程序码ArrayBuffer数据
this.clearFiles()//清除客户端缓存的图片,避免缓存过大,留意方法里的注释
])
.then(res => {
return this.writeFile(res[0].result.buffer);//在客户端创建一个图片
})
.then(res => {
//生成临时图片路径
return new Promise((resolve,reject) => {
const ctx = wx.createCanvasContext('J-canvas');
ctx.drawImage(res, 0, 0, 200, 200);
ctx.draw(true, res => {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 200,
height: 200,
canvasId: 'J-canvas',
success: (res => {
resolve(res.tempFilePath)
}),
fail: (e => {
reject()
})
})
})
});
})
.then(res => {
this.setData({
codeSrc: res
});
})
.catch(e => {
console.log(e)
})
},
/*
此处模拟获取小程序码接口返回ArrayBuffer格式数据,真实情况详见 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html
*/
getCodeBuffer() {
return new Promise((resolve, reject) => {
wx.request({
url: 'https://res.wx.qq.com/wxdoc/dist/assets/img/demo.2333a2a0.png',
responseType: 'arraybuffer',
success(res) {
resolve({
result: {
buffer: res.data
}
})
},
fail: (e => {
reject(e)
})
})
})
},
/*
本例子中writeFile方法,生成的是一个随机名字的图片,所以每次生成图片之前都创建一个目录,而且清除当前目录所有文件,确保这个文件夹下只有一个图片,这样就不会缓存过大,安卓机也不会存在文件不更新的问题
*/
clearFiles() {
const fileSystemManager = wx.getFileSystemManager();
return new Promise((resolve, reject) => {
fileSystemManager.mkdir({
dirPath: dir,
complete: e => {
fileSystemManager.readdir({
dirPath: dir,
success: (res => {
for (let item of res.files) {
fileSystemManager.unlinkSync([dir, item].join('/'))
}
resolve();
}),
fail: (e => {
reject(e)
})
})
}
})
})
},
/*
在test文件夹下生成一个随机名称的图片,并返回路径
*/
writeFile(buffer) {
const filePath = dir + '/' + new Date().getTime() + '.jpg';
return new Promise((resolve, reject) => {
wx.getFileSystemManager()
.writeFile({
filePath,
data: buffer,
encoding: 'binary',
success() {
resolve(filePath)
},
fail() {
reject()
}
});
})
}
})
wxml代码
<canvas canvas-id='J-canvas' style="width:300px;height:300px;"></canvas>
<image src="{{ codeSrc }}" style="width:300px;height:300px;" show-menu-by-longpress></image>
有更好的方法,请留言,谢谢