关于canvas的事件监听


对于js一般的事件监听都是在dom元素的级别上进行的,而canvas内部的元素无法当成dom元素进行那个监听,也就是说对于浏览器,canvas内部有什么元素是根本不关心的。因此要实现canvas内部元素的事件监听,需要自己实现。

以鼠标事件为例,进行思考:

1.坐标转换

      首先必须以canvas元素本身的事件监听为基础,这个用js的事件监听即可实现。问题是当dom事件触发后,我们如何判断是否触发了canvas内部元素事件,触发的是什么事件。

这时需要获取鼠标事件相对于canvas内的坐标。获取事件坐标在canvas时间监听的回调函数中的事件形参event中通过event.clientX和event.clientY获得,但是这只是相对整个页面窗口的坐标,需要转换成相对canvas的坐标。

      canvas对象有一个方法getBoundClientRect(),返回的是canvas元素的边界框对象,设返回对象为bbox, 此对象的left与top属性即为canvas左上角点相对窗口的坐标,将事件坐标与canvas坐标相减,得到相对于canvas的坐标。

      然而还有一个问题,canvas内部而言,1像素不一定等于浏览器中的1像素,这是因为,canvas作为dom元素有自身的宽高,canvas的内部也有宽高属性,这两个大小中有一个缩放关系,导致单位的不统一,之前得到的坐标是相对于

浏览器的单位比例而言的,要转换成canvas的单位比例,将横纵坐标各乘于(canvas.width / bbox.width)和(canvas.height / bbox.height)即可。

      转换代码如下:

1       //传入canvas对象,与事件坐标参数
var windowToCanvas = function(canvas, x, y){ 2 var bbox; 3 bbox = canvas.getBoundingClientRect(); 4 return { 5 x: (x - bbox.left) * (canvas.width / bbox.width), 6 y: (y - bbox.top) * (canvas.height / bbox.height) 7 }; 8 };

2.监听器对象

          对鼠标事件的监听是以坐标范围为基础的,一个事件对应一个坐标范围,若点击事件的坐标在该范围内,便出发对应的自定义事件。代码如下:

 1       var canvasListener = function(canvas){
 2         var func;
 3         this.canvas = canvas;
 4         func = function(obj){
 5           var listener;
 6           listener = obj;
 7           return function(e){
 8             return listener.dealEvents(e);
 9           };
10         };
11         this.canvas.click(func(this));
12         this.events = [];
13       };
//添加自定义事件,参数为坐标范围(左上角坐标与范围宽高)和事件回调函数
14 canvasListener.prototype.addEvent = function(x, y, width, height, callback){ 15 var newEvent; 16 newEvent = { 17 x: x, 18 y: y, 19 width: width, 20 height: height, 21 callback: callback 22 }; 23 this.events.push(newEvent); 24 };
//点击事件触发时,判断该触发哪个自定义事件
25 canvasListener.prototype.dealEvents = function(e){ 26 var loc, i$, ref$, len$, event; 27 loc = windowToCanvas(this.canvas[0], e.clientX, e.clientY); 28 for (i$ = 0, len$ = (ref$ = this.events).length; i$ < len$; ++i$) { 29 event = ref$[i$]; 30 if (loc.x >= event.x && loc.x < event.x + event.width && loc.y >= event.y && loc.y < event.y + event.height) { 31 event.callback(); 32 } 33 } 34 };

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM