在小程序【打卡圈】的开发过程中,需要实现作业批改的需求,这就需要实现图片的编辑涂鸦添加对号叉号等贴纸,在其中有一个需求那就是涂鸦的撤回,在canvas中绘制的了很多步,点击撤回总能回退到上一步操作,当时在想这个需求该如何去实现,每一步绘制结束去 生成一张图片?回退显示之前的图片吗,这样处理生成图片太频繁,再有就是调用canvas本来属性就不稳定,还去频繁的生成图片,这不更容易翻车吗,继续查看文档,发现了两个属性canvasPutImageData,canvasGetImageData,这不正是我需要的API吗,准备开干
wx.canvasGetImageData({ canvasId: 'myCanvas', x: 0, y: 0, width: 100, height: 100, success(res) { console.log(res.width) // 100 console.log(res.height) // 100 console.log(res.data instanceof Uint8ClampedArray) // true console.log(res.data.length) // 100 * 100 * 4 } })
const data = new Uint8ClampedArray([255, 0, 0, 1]) wx.canvasPutImageData({ canvasId: 'myCanvas', x: 0, y: 0, width: 1, height: 1, data: data, success (res) {} })
思路,在每次触摸结束的时候触发canvasGetImageData保存当前画布上的所有像素点,并且压入一个数组变量中,当点击回退的时候从数组中拿出上一步的数据,再调用canvasPutImageData将数据绘制在canvas中,且从数组中弹出最后一个数据。
在开发过程中发现经常会报错canvasPutImageData: invalid data format
但是打印数据显示正确,最终发现canvas 的宽高是引起报错的罪魁祸首
当height或者width存在小数时会导致回退失败
解决方案:
在获取图片信息回调中getImageInfo
计算图片适应屏幕时取整
downLoadBgImg:function(){//获取需要编辑的图片信息 let _this =this wx.getImageInfo({ src: _this.bgImgUrl, success:(res)=> { if(res.errMsg!='getImageInfo:ok'){ _this.$base.defaults('获取图片资源出错') return false; } _this.bgImgTempFilePath = res.path _this.bgImgTempFilePathHeight = res.height _this.bgImgTempFilePathWidth = res.width if(res.width>=res.height){//横图 _this.bgImgWidth = Math.ceil(res.width) _this.bgImgHeight = Math.ceil(res.width/_this.windowWidth * res.height) _this.drawCanvasHeight = Math.ceil(res.width/_this.windowWidth * res.height) _this.drawCanvasWidth = Math.ceil(res.width) }else{//竖图 _this.bgImgHeight = Math.ceil(_this.bodyHeight) _this.bgImgWidth = Math.ceil(_this.bodyHeight/res.height *res.width) _this.drawCanvasHeight = Math.ceil(_this.bodyHeight) _this.drawCanvasWidth = Math.ceil(_this.bodyHeight/res.height *res.width) } _this.ctx = wx.createCanvasContext('drawCanvas'); _this.canvasUndoPush();//缓存一次空画布 }, fail: (err) => { _this.$base.defaults('获取图片资源出错') } }); },