使用场景
小程序中有一个这样的场景:一个图片(包括了背景图,二维码,标题),类似于zfb中的每天扫一扫,方便用户保存在本地。
问题说明
小程序码通过后台接口获取,格式如下:'data:image/jpg;base64,/9j/4AAQSkZJRgAB......'
通过canvas画出来之后,在微信开发者工具上有效,在真机上无效。
随后就踩上了这个坑,小程序的canvas局限性很多。主要体现在如下几点:
- 不支持base64图片;
- 图片必须下载到本地后才能绘制到画布上;
- 图片域名需要在管理平台加入downFile安全域名;
- canvas属于原生组件,在移动端会置于最顶层;
- 通过SelectorQuery只能拿到节点的style,而无法获取文本节点的内容以及图片节点的链接。
解决方法
先把小程序码通过小程序API中的FileSystemManager.writeFile()接口写入本地并获取到一个临时URL。
示例代码:
export const writeFile = (base64Str) => new Promise((resolve, reject) => {
// 后台返回的base64格式数据的回车换行换为空字符''
const base64Image = base64Str.split(',')[1].replace(/[\r\n]/g, '')
// 文件管理器
const fsm = wx.getFileSystemManager()
// 文件名
const FILE_BASE_NAME = 'tmp_base64src'
// 文件后缀
const format = 'png'
// 获取当前时间戳用于区分小程序码,防止多次写进的小程序码图片都一样,建议通过不同的列表ID来区分不同的小程序码
const timestamp = (new Date()).getTime()
// base转二进制
const buffer = wx.base64ToArrayBuffer(base64Image)
// 文件名
const filePath = `${wx.env.USER_DATA_PATH}/${timestamp}share.${format}`
// 写文件
fsm.writeFile({
filePath,
data: buffer,
encoding: 'binary',
success () {
// 读取图片
wx.getImageInfo({
src: filePath,
success (res) {
const img = res.path
// 把需要画出来的图片的临时url暴露出去
resolve(img)
reject()
},
fail (e) {
console.log('读取图片报错')
console.log(e)
},
error (res) {
console.log(res)
}
})
},
fail (e) {
console.log(e)
}
})
}).catch((e) => {
console.log(e)
})
页面中进行使用:
import { writeFile } from '../../utils/wxFunc'
const getUseCode = () => {
//code为base64格式的小程序码
writeFile(code).then((img) => {
console.log(`可使用的小程序码:${img}`) // img格式:http://usr/1599468897794share.png
}).catch((e) => {
console.log(e)
})
}
这样的缺点在于每调用一次写一个文件,文件会越写越多,当文件管理器中文件总大小超过最大限制则会报错。解决方法:在写入文件之前先做一次删除操作,关键代码如下:
// 删除存储的垃圾数据
export const removeSave = () => new Promise((resolve) => {
// 文件管理器
const fsm = wx.getFileSystemManager()
// 获取文件列表
fsm.readdir({
dirPath: wx.env.USER_DATA_PATH, // 当时写入的文件夹
success (res) {
res.files.forEach((el) => { // 遍历文件列表里的数据
// 删除存储的垃圾数据
if (el !== 'miniprogramLog') { // 过滤掉miniprogramLog
fsm.unlink({
filePath: `${wx.env.USER_DATA_PATH}/${el}`, // 文件夹也要加上,如果直接文件名会无法找到这个文件
fail (e) {
console.log('readdir文件删除失败:', e)
}
})
}
})
resolve()
}
})
})
// 在页面调用方法
import { writeFile,removeSave } from '../../utils/wxFunc'
removeBeforeFiles () {
removeSave()
},
getUseCode () {
//codeUrl为base64格式的小程序码
writeFile(code).then(img => {
console.log(`可使用的小程序码:${img}`) // img格式:http://usr/1599468897794share.png
}).catch(e => {
console.log(e);
})
},
最后就accomplish啦!感谢
微信小程序中base64格式的小程序码通过canvas画出来无效_微信小程序 base64 图片太大 canvas 绘制不了-CSDN博客