如何给Canvas内部元素添加监听事件

144 阅读3分钟

前引

前端给页面中DOM元素添加事件是比较简单的事情,但是Canvas绘制出来的图形是一个整体,如何给 Canvas内部的元素添加监听事件呢? 只有能精准控制Canvas内部元素,才能在项目中更好的使用它! 本文首先用Canvas基本用法画一个具有多张图片的小例子,然后逐步探讨如何监听Canvas整体、比较 多种监听Canvas内部元素的方式,总结最优的监听方式! 最后举一个在项目中可能会用到的案例场景,希望对你有所启发!

Canvas基本用法

是一个可以使用脚本 (通常为JavaScript) 来绘制图形的 HTML 元素。例如,它可以用于绘制 图表、制作图片、制作简单的动画、数据可视化、图片编辑、实时视频处理等领域。 Canvas API 主要聚焦于 2D 图形。 使用Canvas绘图之前,必须先要创建一个画布,生成一个渲染上下文,如下:

`const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");`

Canvas可以绘制矩形、圆形、多边形等常规的图形,也可以绘制任何其他形状的图形。

Canvas画一个具有多个内部元素的DEMO

为了后面在此demo上添加事件,绘制多个图片,如下:

Image20250220141728092.png

Image20250220141818019.png

添加的事件有哪些?

事件包括:

鼠标事件:

click(点击)
dblclick(双击) 
mouseover(鼠标移入)
mouseout(鼠标移出) 
mouseenter(鼠标移入)
mouseleave(鼠标移出) 
mousedown(鼠标按下)
mouseup(鼠标抬起)
mousemove(鼠标移动) 
mousewheel(鼠标滚轮)

键盘事件:

keydown(键盘按下)
keyup(键盘抬起)
keypress(键盘按下) 

鼠标事件要注意的点:

1. mouseover和mouseenter 都是鼠标移入时触发,但区别是 mouseover事件 在鼠标指针移入被选元素、 被选元素的子元素都会触发,而 mouseenter事件 只有移入被选元素时才会触发,移入被选元素的子 元素不会触发; 
2. mouseout和mouseleave 这一对也是同理; 
键盘事件要注意的点:如果按住键盘不放开的话,会重复触发 keypress 事件。

监听Canvas本身的事件

给 Canvas 整体添加事件,和监听其他 DOM 事件一样,使用 addEventListener() 或者 onxx() 等方法即 可。

1.png

2.png

监听Canvas内部元素的事件

在实际应用中,只能监听 Canvas 整体的事件,是远远不够的,更多的应用场景需要精确的操 作 Canvas 内部的某个元素,例如:这里我需要点击某个图片时,显示此图片的详情(拍摄时间、图片 作者、图片的标记等)。 要实现这个功能,首先要解决当前鼠标操作的内部元素是哪个?如何计算是本文的重点内容,有如下方式:

方法一:手动计算内部元素(只适用规则图形)

如果内部元素是矩形、圆形等常规图形,可以通过简单的计算知道元素的坐标范围,可以使用此种方 式,其他不规则图形不建议使用此方式,因为计算量巨大,可以尝试方法二。

3.png

4.png

5.png

6.png

7.png

方法二:使用 isPointInPath() 方法计算内部元素

CanvasRenderingContext2D.isPointInPath() 是 Canvas 用于判断在当前路径中是否包含检测点。返回 一个 Boolean 值,当检测点包含在当前路径内或指定的路径内,返回 true;否则返回 false;

实例用法:

8.png

我们这里利用此方法,需要在绘制图片时再根据图片形状绘制一个看不见的路径,专门用来检查点位是 否在路径内,在路径内即代表在图片元素范围内。

9.png

11.png

12.png

13.png

14.png

15.png

方法三:使用 new Path2D() 优化方法二

22.png

33.png

34.png

35.png

方法四:使用PixiJs实现监听事件

44.png

45.png