在小程序【打卡圈】的开发过程中,需要实现作业批改的需求,这就需要实现图片的编辑涂鸦添加对号叉号等贴纸,在其中有一个需求那就是涂鸦的撤回,在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('获取图片资源出错')
}
});
},
