前言:简单的框选需求踩坑无数,此刻只想说句轻舟已过万重山。
- 微信官方Canvas新旧接口问题
- 轨迹不规则问题
- 再上一次基础上画图问题
- 安卓真机drawImage模糊问题
- 安卓真机fillRect不能为负值问题
- 撤回、恢复、清空问题
- 黑白蒙版生成问题(AI接口需要)
1、微信官方Canvas新旧接口
由于mpvue框架限制(无数次吐槽这个框架6年前就已经不再维护了),只能使用旧版CanvasContext接口。 uniapp框架建议使用新版 Canvas2D 接口。
js
// 旧版
const ctx = wx.createCanvasContext('myCanvas');
// 新版
const query = wx.createSelectorQuery()
query.select('#myCanvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
ctx.fillRect(0, 0, 100, 100)
})
}
2、轨迹不规则
绘制矩形比较简单,一笔下来没有问题,但是如果过程轨迹反复弯曲,就会出现下面情况
如果只是画一次,那么直接ctx.draw(false)就好了不会出现这个问题,但是需求是可以反复绘画矩形。
3、再上一次基础上画图
既然是要在上一次基础上画图,那么ctx.draw(true)就要这样,但是这样又会出现问题2。于是换个思路,每次画完都保存一次临时图片,再上一次临时图片基础上画图。代码如下
js
this.ctx.draw(true, () => {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: this.canvasWidth,
height: this.canvasHeight,
destWidth: this.canvasWidth,
destHeight: this.canvasHeight,
canvasId: 'myCanvas',
success: res => {
this.allDrawWorksPath.push(res.tempFilePath)
},
fail: res => {
console.log('获取画布图片失败', res);
}
})
4、安卓真机drawImage模糊问题
本以为一切就大功告成了,模拟器和ios没有问题,但是到了andriod真机,就会出现画的矩形越多,之前的矩形就越模糊,查阅了很多方法比如放大图片比例并未解决,比如动态改变canvasid,但是这个方法尤其的麻烦。于是突然奇想,在canvas和图片两层之间夹一层绘画轨迹图片,有点类似于汉堡,说到这突然想起电影《无双》里面一个片段,两层之间夹一层水印的道理
于是有了下面代码
html
<canvas class="mycanvas" canvas-id="myCanvas" disable-scroll @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" :style="{'width': canvasWidth+ 'px', 'height': canvasHeight+'px', left: canvasLeft + 'px', top: canvasTop + 'px',zIndex: 9}"></canvas>
html
<image :src="轨迹图片" :style="{'width': canvasWidth+ 'px', 'height': canvasHeight+'px', left: canvasLeft + 'px', top: canvasTop + 'px',zIndex: 8,'position':'absolute'}" />
<image src="真实图片" :style="{'width': canvasWidth+ 'px', 'height': canvasHeight+'px', left: canvasLeft + 'px', top: canvasTop + 'px',zIndex: 7,'position':'absolute'}" />
5、安卓真机fillRect不能为负值
就当再一次以为大功告成的时候,结果安卓真机毫无意外的又出了意外。右下向左上框选的时候,没有显示。这个问题就是源于安卓机不支持fillRect()方法里面的width和height为负值的情况。于是将fillRect拆成fill和rect两个方法。先去rect再去fill,巧妙解决问题
js
this.ctx.rect(this.p1.x, this.p1.y, rectWidth, rectHeight);
this.ctx.fill()
6、撤回、恢复、清空
这三个问题就比较好解决了,但是还是有坑。如果使用轨迹重绘,那么在真机上会看到重绘过程,用户体验极差尤其是轨迹太多的情况。于是采用临时图片的方式,不用担心模拟器会闪屏,再真机上是没有任何问题的。
js
this.ctx.draw(true, () => {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: this.canvasWidth,
height: this.canvasHeight,
destWidth: this.canvasWidth,
destHeight: this.canvasHeight,
canvasId: 'myCanvas',
success: res => {
this.allDrawWorksPath.push(res.tempFilePath) // 没错就是这一步很关键
},
fail: res => {
console.log('获取画布图片失败', res);
}
})
});
7、黑白蒙版生成问题(AI接口需要)
由于业务需要,要将画好的图片变成黑白蒙版以供AI接口。所以还需要一个canvas来单独绘制黑白蒙版,过程踩过的坑就不多说了,最后只有这个办法最有效。一定要最后点击的时候再去生成蒙版,再过程生成会出现卡顿现象。秒生成。
在此之前,已经实现了涂抹功能,也踩过很多坑,总的来说比款选坑少,就不多描述了。。。最后贴上效果图