大家好,我是南宫,今天来写一篇关于canvas绘制“图片选区”的博客。
最近我接到了一个新的任务,要求做一个新的弹窗,里面可以点击按钮,切换配置的能力。其中一个能力涉及到在图片上用鼠标拖动,框选出一个区域,这看起来比较复杂,各种百度无果,我只能自己从零开搞。历时两天终于弄完了,所以现在写一篇博客来记录一下这个思路和实现的过程。
一、成品效果
截图如下:
初始状态是这样的,左右是两张相同的图片,中间有一个钩的按钮。
左边的图可以用鼠标框出一个虚线框。具体来说是按下鼠标后,在图片区域移动鼠标,就能看到一个由按下鼠标的地方和鼠标当前位置作为对角线而确定的矩形。鼠标抬起或移出图片区域,则停止绘图,矩形形状变得稳定。
确定后点击绿色的钩,右边的图片区域在相同位置上也绘制出一个矩形。
二、实现思路
这个思路完全是我根据微信截图的时候在图上绘制矩形框的过程脑补出来的,具体如下:
1. 想要在图片区域上画出矩形框,那么就要在图片区域上放置一个透明画布,而且是盖在图片上面,大小与图片相同。(由于我不知道图片要用多大的,所以我在图片外面套了一层相对定位的div,canvas弄成绝对定位放在里面,就可以完美满足这个要求)
2.右边要显示左边的结果,所以左右的canvas和图片大小要一致。(我这边仅仅是外层div是左右浮动的不同,里面的图片和canvas样式都相同)
3. 绘制选区的时候,是先按下鼠标,然后才进入绘制的状态。之后移动鼠标,绘制的矩形也会移动到鼠标现在所在的点。然后抬起鼠标,就不再是绘制的状态。(所以要在左边的canvas上监听鼠标按下、移动和抬起的事件)
4. 鼠标按下的时候要做的事情是:让canvas进入绘图状态,获取当前点击的位置相对于canvas的坐标,并记录。
5. 鼠标移动的时候,要记录当前的位置,获取当前的位置相对于canvas的坐标,并且跟起点相比较。横坐标相减得到宽度,纵坐标相减得到高度。(需要判断当前是否为绘图状态,只有为绘图状态,才会这样)
如果宽高都大于0,那就把这两个点连成的线当成矩形的对角线,然后计算出剩余两个点的位置。把4个点的坐标记录到位置数组中。
6. 现在,得到了矩形4个点的坐标,把它们连接起来,用虚线绘制。考虑到每次移动都会有新的坐标,所以要用clearRect在绘制之前清空上一次的矩形。
7. 鼠标抬起后,让canvas解除绘图状态。
8. 点击中间的钩,让右边的canvas根据记录下来的位置数组,在右边的canvas上画出红色的矩形。
三、实现的过程中遇到的问题
1.canvas的高度怎么计算?
canvas跟图片一样,宽高涉及到了像素,那可不是简单用CSS设置宽高就可以的。canvas的宽高是有默认值的(好像是300*150),如果不设置canvas的像素宽高,单单设置CSS的宽高,那画出来是分分钟变形的。
但是图片多大,我也不知道,所以我用了el.getBoundingClientRect()来获取图片的宽高和位置,把宽高动态绑定到canvas上。作为初始化canvas的操作。(位置可以用来计算鼠标相对于canvas的位置)
2. 矩形的鼠标数