Canvas的分块处理(Canvas的性能优化)

(想看分块画图问题的请直接移到最后)

最近,做了一个项目,需求是为一个页面增加绘画功能,虽然只是简单的画几笔,不过由于考虑以后可能会有其他需求,比如画方块,圈之类的,所以还是用了canvas来进行处理,效果如下图:

其实最初的想法非常简单,就是直接写一个canvas,让其覆盖在这个页面上方,然后在上面进行画图功能即可实现,这里需要注意的是canvas你单独使用position并不好使,必须加上width和height才可以正常使用。

由于画的这个页面带有滚动条,需求是边画图边滚动,因此position我使用了absolute,然而因为页面会进行加载,因此canvas也会不断扩大,当canvas高度超过13000左右后,页面画图会出现明显的卡顿,当超过20000左右后,几乎是画一笔等几秒才会延迟出现。这样带来了极其不好的用户体验,而且随着页面不断增加会导致其无法使用。查阅了相关资料后,我选择了对canvas进行分块处理,以上图为例:

我把整个canvas进行了分块处理,使得每个canvas加载的区域只对应其块模块大小,经过此次处理后,可以明显感觉到canvas性能大幅度提升,没有了之前的卡顿现象。但是问题也随之而来,最大的问题就是canvas与canvas之间的画图在从上到下的时候会出现断层,如下图:

这个问题原因是由于每个canvas都是各自独立存在的,每个canvas的画图变量画图时每次都会独立初始化,这样一来即便上一个canvas允许画图也无法影响下一个canvas,知道原因了处理起来就十分简单,我们可以使所有的canvas用同一个变量进行判断canvas与canvas之间经过时是否可以绘画,这样就不会出现从这个canvas到下个canvas的时候就无法画图了。

本来以为万事大吉了,但是随即就发现事情没有那么简单,出现了一个比较严重的问题,就是如果你画图画得稍微快了那么页面就会呈现这样的效果:

注意这个效果只会在你从以非常快的速度从这个canvas画到下一个canvas中才会出现,如果你慢慢画是不会出现这个问题的。经过查阅资料后发现,原理是因为你如果画的非常快,那么其实记录的点是非常少的,请看下图:

假如上述图是一个canvas,那么我们在canvas上绘制一条线时其实是在canvas上先获取了画图的起点和终点,然后再在其之间画了一条线的,整个过程非常迅速。再看下图:

当我们画的很慢的时候,那么canvas上就会标记很多个点,然后迅速将其之间连线。但是如果我们画的很快,那么canvas上方的点就会非常稀少,比如刚刚断层那个情况就是其实只有2个点:

此时大家也许会有疑问,明明不是有2个点吗,为什么没有连接起来呢?原因很简单,A点是我从canvas1的mouseleave中所得到得点,B点则是我从canvas2的mouseenter中所得到的点,而canvas1和canvas2其实是分开算的坐标的,举个例子,比如每个canvas的坐标是从(0,0)到(200,200),那么假如A点是(120,180),那么B点可能就是(80,20),如果此时你在B点调用绘图那么就很可能会出现这样的情况:

它会先从你的canvas中找出一个C点,这个C的坐标是(120,180)然后从B到C之间画一条线出来,这样当然不是我们想要的结果。那么该怎么办呢?既然从canvas2画不了,那么我们从canvas1画会怎么样呢,毕竟canvas1的时候还没有得到B点,那么从canvas1会画出什么样的效果呢,带着这个疑惑,我试了下在mouseleave的时候继续画图,然后有了发现。效果如下图:

啊啊啊!上面的线画出来了(这个图是因为我手动画的所以有点别扭),但是下面的还是没有,没关系我们至少已经成功一半了。那么我们只要能理解这一半,另一半还怕找不到吗😜。带着这样的疑惑我去研究了下为什么上面的线可以画出的原因。有了重大的发现,原来上面的线之所以可以画是因为还隐藏着第3点D,如下图:

D这个点不仅和B点重合而且它用的坐标竟然是以canvas1为基础的坐标,刚刚我们说的A(120,180),B(80,20),那么D其实是(80,220),没错它是canvas1里面没有的点,但是由于它的坐标为canvas1指明了方向,因此便有了上面的那条至关重要的线。知道这个原理后就非常简单了,我们直接算A点的影子E点的相对于canvas2的坐标然后到B点时,我们去画出E到B的距离这样就可以把另一半补齐了。E点坐标很快算出来是(120,-20)。这样一来断线问题就已经解决了。

代码我周末整理下在提交出来,谢谢大家观看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值