记canvas画笔笔迹的多次优化过程

我们的项目是面向学校老师的教学软件,所以肯定少不了互动白板的功能,而这个里面的画笔功能是由我来开发的,下面介绍这个过程中遇到的问题以及解决方法。

首先给大家明确下由于软件中的画布可以自由移动,会超出屏幕显示范围,同时支持点擦和线擦,所以需要存储所有点坐标。

第一版简单画笔实现并优化掉折线感

第一版实现的肯定是很简单的画笔线条,由给定的鼠标坐标位置连线画出线段,主要使用的canvas的API方法有:beginPath moveTo  lineTo stroke。不过很快发现当鼠标快速画曲线时出现很明显的拐点,这里要用到贝塞尔曲线来解决,具体可参考《利用贝塞尔绘制平滑曲线》。

第二版解决快速画线时笔迹跟不上鼠标移动的问题

实现了贝塞尔曲线的绘制,同时也产生新的问题,绘制过程中会出现线条的延长跟不上鼠标的情况(这是由于贝塞尔曲线的应用引起的,二次贝塞尔曲线绘制的时候需要三点确定起始点和控制点,《利用贝塞尔绘制平滑曲线》有具体讲解,看懂就能明白为什么会跟不上了)。

由于我们存储了所有点坐标,所以解决这个题也好办,就是mousemove触发绘制时都遍历一遍本条线上所有点来绘制这条线。

所以每次鼠标移动采用的绘制过程是先清除画布,再绘制整条笔迹。当然这里我们已经采用了一个优化性能的方式,就是分层canvas,绘制中的画笔笔迹使用drawingCanvas,当鼠标释放确定了一条线后,这条线会移动到主画布mainCanvas上,达到动静分离。这样每次取出当前线条的所有点坐标,利用贝塞尔绘制出平滑的曲线。并绘制到最后一个鼠标点位置处,解决跟不上鼠标移动的问题。

第三版解决点擦和线擦不连续的问题

我们实现的橡皮擦除并不是像大家熟悉的方式设置globalCompositeOperation,去盖住原有图形的方式。《清除canvas画布内容--点擦除+线擦除》有详细介绍我们的方法,主要采集鼠标滑过的点利用canvas缓存颜色的图形拾取方式来找到要擦除的图形及具体应该去掉哪几个坐标点,或者哪条线。但是这样如果鼠标滑动很快的话,两个mousemove触发的间隔距离就会很大,那么中间的线都不会被擦除掉。针对这个问题,主要采用了中间补点的方式来模拟增加采集鼠标点的密度。

记canvas画笔笔迹的多次优化过程

记canvas画笔笔迹的多次优化过程

1 //橡皮优化,鼠标快的时候擦除不干净 2 let dis = XlMath.getInstance().distance(that.eraserLastPoint, p); 3 // let isDraw = false; 4 if (dis > eraserRadius) { 5 let basePoint = that.eraserLastPoint; 6 for (let i = 0; i < 1000; i++) { 7 basePoint = new Point((p.x - that.eraserLastPoint.x) * eraserRadius / dis + basePoint.x, (p.y - that.eraserLastPoint.y) * eraserRadius / dis + basePoint.y); 8 if ((basePoint.x - p.x) * (that.eraserLastPoint.x - p.x) < 0 || (basePoint.y - p.y) * (that.eraserLastPoint.y - p.y) < 0) 9 break; 10 else { 11 let eraserReturn = that.eraser(basePoint); 12 if (eraserReturn) { 13 editor.courseware.draw(false, true); 14 if (currentEditMode == EditMode.elementEraser) 15 editor.bdCanvas.drawPenStatusForElement(true); 16 } 17 } 18 } 19 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywwjj.html