最近在学小程序,在把当前画布指定区域的内容导出并生成图片保存到本地这个知识点上踩坑了。
这里用到的方法是: wx.canvasToTempFilePath(),该方法作用是把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径。(详情 )
这里先来分析一下这句话:导出当前画布指定区域的内容并生成图片 。这里以画一个矩形并将该矩形保存到本地相册为例。
首先我们要做的是先在画布上画一个矩形,其次是利用 wx.canvasToTempFilePath()方法导出画布指定区域的内容,这里当然就是要保存这个矩形了,根据该方法返回的文件路径,然后可以使用wx.saveImageToPhotosAlbum()方法将图片保存到本地相册了。
思路清晰了,现在可以着手实现了。
index.wxml中画布代码如下:
画矩形代码如下(该代码放在save方法中):
const ctx = wx.createCanvasContext('myCanvas') ctx.setFillStyle('red')ctx.fillRect(20, 20, 150, 100)ctx.draw()
此时点击按钮调用save方法,出现的效果如下:
现在要做的就是将这个红色矩形导出来并存放到本地相册。根据文档的提示:需要在 draw
回调里调用wx.canvasToTempFilePath()方法才能保证图片导出成功
那么以上代码可以修改为这样(此部分代码存放在draw方法里):
wx.canvasToTempFilePath({ x: 20, y: 20, width: 150, height: 100, destWidth: 150, destHeight: 100, canvasId: 'myCanvas', success: function (res) { console.log(res.tempFilePath) // 返回图片路径 }})
这样就完了吗?并没有,上面只是导出了矩形并返回了图片路径而没有将图片存放到本地,要实现这一点,还需要调用wx.saveImageToPhotosAlbum()方法,根据返回的路径来保存该图片到本地。
那么以上代码又可以更改为(此部分代码存放在draw方法里):
wx.canvasToTempFilePath({ x: 20, y: 20, width: 150, height: 100, destWidth: 150, destHeight: 100, canvasId: 'myCanvas', success: function (res) { wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, }) }})
进行到这一步,效果基本上已经实现了,注意,是基本上,,,,这里还存在着一个小bug,那就是在第一次生成图片并保存的时候是一张相同大小但是却是透明的图片,并非是期望的红色矩形,而之后生成的就是红色的矩形图片了,只有第一次不是,这是为什么呢?仔细分析了下,可能原因是,第一次保存图片的时候,矩形可能并没有绘制完成,因而裁剪后保存的是一张相同大小但是透明的图片,于是我将上述代码稍微做了调整,给它加了一个定时器。
const ctx = wx.createCanvasContext('myCanvas') ctx.setFillStyle('red') ctx.fillRect(20, 20, 150, 100) ctx.draw(true, setTimeout(function () { wx.canvasToTempFilePath({ x: 20, y: 20, width: 150, height: 100, destWidth: 150, destHeight: 100, canvasId: 'myCanvas', success: function (res) { wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, }) } }) },100))
好了,现在bug已经解决了,每次都能实现预期的效果了。
补充:最近开发小程序,使用了保存图片到本地,按照正常流程走发现是没有问题的,也就是说不存在第一次保存为空的情况,不需要再使用定时器来解决了。保存图片到本地需要授权问题:
wx.saveImageToPhotosAlbum({ filePath: downUrl, // 需要保存的图片地址 success(res) { wx.showToast({ title: '图片保存中...', icon: 'loading', duration: 1000 }); setTimeout(function () { wx.showToast({ title: '图片保存成功', icon: 'success', duration: 2000 }) }, 1000) }, fail: function (res) { if (res.errMsg === "saveImageToPhotosAlbum:fail auth deny" || res.errMsg == "saveImageToPhotosAlbum:fail:auth denied" || res.errMsg == "saveImageToPhotosAlbum:fail authorize no response") { wx.showModal({ title: '提示', content: '需要授权才可保存图片', showCancel: false, success(res) { if (res.confirm) { wx.openSetting({ success(settingdata) { if (settingdata.authSetting["scope.writePhotosAlbum"]) { wx.showToast({ title: '获取权限成功,再次点击可保存图片', icon: 'none', duration: 2000 }) } else { wx.showToast({ title: '获取权限失败', icon: 'none', duration: 2000 }) } }, fail() { wx.showToast({ title: '获取权限失败', icon: 'none', duration: 2000 }) } }) } } }) } }})