百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>html5教程> HTML5 Canvas的事件处置介绍
分享文章到:

HTML5 Canvas的事件处置介绍

发布时间:09/01 来源:未知 浏览: 关键词:
这篇文章主要介绍了HTML5 Canvas的事件处置介绍,本文讲解了Canvas的限制、给Canvas元素绑定事件、isPointInPath办法、轮回重绘和事件冒泡等内容,需要的伴侣可以参照 下

DOM是Web前端领域非常重要的组成部分,不仅在处置HTML元素时会用到DOM,图形编程也一样会用到。比方SVG画图,各种图形都是以DOM节点的情势插入到页面中,这就意味着可以使用DOM办法对图形停止操纵。比方有一个<path id="p1">元素,可以直接用jquery增添click事件$('#p1').click(function(){…})"。然而这种DOM处置办法在HTML5的Canvas里不再适用,Canvas使用的是别的一套机制,不管在Canvas上绘制多少图形,Canvas都是一个团体,图形本身实际都是Canvas的一部分,不成独自猎取,所以也就没法直接给某个图形增添JavaScript事件。

Canvas的限制

在Canvas里,所有图形都绘制在帧上,绘制办法不会将绘制好的图形元素作为一个返回值输出,js也没法猎取到已经绘制好的图形元素。比方:

复制代码

代码如下:

cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
theRect = ctx.rect(10, 10, 100, 100);
ctx.stroke();
console.log(theRect);     //undefined

这段代码在canvas标签里绘制了一个矩形,第一可以看到绘制图形的rect办法没有返回值。假如翻开阅读器的开发者工具,还可以看到canvas标签内部没有增添任何内容,而在js里猎取到的canvas元素乃至当前的上下文,也都没有任何表示新增图形的内容。

所以,前端常用的dom办法在canvas里是不适用的。比方点击上面Canvas里的矩形,实际点击的是整个Canvas元素。

给Canvas元素绑定事件

由于事件只能到达Canvas元素这一层,所以,假如想进一步深入,识别点击发生在Canvas内部的哪一个图形上,就需要增添代码来停止处置。根本思绪是:给Canvas元素绑定事件,当事件发生时,检查事件对象的位置,然后检查哪些图形覆盖了该位置。比方上面的例子里画过一个矩形,该矩形覆盖x轴10-110、y轴10-110的范畴。只要鼠标点击在这个范畴里,就可以视为点击了该矩形,也就可以手动触发矩形需要处置的点击事件。思绪其实比力简便,但是实现起来还是轻微有点复杂。不仅要思考这个推断历程的效力,有些地方还需要从新推断事件类型,设定要从新定义一个Canvas内部的捕捉和冒泡机制。

第一要做的,是给Canvas元素绑定事件,比方Canvas内部某个图形要绑定点击事件,就需要通过Canvas元素代理该事件:

复制代码

代码如下:

cvs = document.getElementById('mycanvas');
cvs.addEventListener('click', function(e){
  //...
}, false);

接下来需要推断事件对象发生的位置,事件对象e的layerX和layerY属性表示Canvas内部坐标系中的坐标。但是这个属性Opera不支撑,Safari也打算移除,所以要做一些兼容写法:

复制代码

代码如下:

function getEventPosition(ev){
  var x, y;
  if (ev.layerX || ev.layerX == 0) {
    x = ev.layerX;
    y = ev.layerY;
  } else if (ev.offsetX || ev.offsetX == 0) { // Opera
    x = ev.offsetX;
    y = ev.offsetY;
  }
  return {x: x, y: y};
}

//注:使用上面这个函数,需要给Canvas元素的position设为absolute。

此刻有了事件对象的坐标位置,下面就要推断Canvas里的图形,是什么覆盖了这个坐标。

isPointInPath办法

Canvas的isPointInPath办法可以推断当前上下文的图形可否覆盖了某个坐标,比方:

复制代码

代码如下:

cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
ctx.rect(10, 10, 100, 100);
ctx.stroke();
ctx.isPointInPath(50, 50);     //true
ctx.isPointInPath(5, 5);     //false

接下来增添一个事件推断,就可以推断一个点击事件可否发生在矩形上:

复制代码

代码如下:

cvs.addEventListener('click', function(e){
 p = getEventPosition(e);
 if(ctx.isPointInPath(p.x, p.y)){
   //点击了矩形
 }
}, false);

以上就是处置Canvas事件的根本办法,但是上面的代码还有局限,由于isPointInPath办法仅推断当前上下文环境中的途径,所以当Canvas里已经绘制了多个图形时,仅能以最后一个图形的上下文环境来推断事件,比方:

复制代码

代码如下:

cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.rect(10, 10, 100, 100);
ctx.stroke();
ctx.isPointInPath(20, 20);     //true
ctx.beginPath();
ctx.rect(110, 110, 100, 100);
ctx.stroke();
ctx.isPointInPath(150, 150);     //true
ctx.isPointInPath(20, 20);     //false

从上面这段代码可以看到,isPointInPath办法仅能识别当前上下文环境里的图形途径,而此前绘制的途径,没法回溯推断。这种问题的解决办法是:当点击事件发生时,重绘所有图形,每绘制一个就使用isPointInPath办法,推断事件坐标可否在该图形覆盖范畴内。

轮回重绘和事件冒泡

为了实现轮回重绘,所以就要将图形的根本参数事先留存下来:

复制代码

代码如下:

arr = [
 {x:10, y:10, width:100, height:100},
 {x:110, y:110, width:100, height:100}
];

cvs = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');

draw();

function draw(){
 ctx.clearRech(0, 0, cvs.width, cvs.height);
 arr.forEach(function(v){
   ctx.beginPath();
   ctx.rect(v.x, v.y, v.width, v.height);
   ctx.stroke();
 });
}

上面的代码事先将两个矩形的根本参数留存下来,每次调取draw办法,就会轮回调取这些根本参数,用于绘制两个矩形。这里还使用了clearRect办法,用于在重绘时清空画布。接下来要做的是增添事件代理,乃至在重绘时对每一个上下文环境使用isPointInPath办法:

复制代码

代码如下:

cvs.addEventListener('click', function(e){
 p = getEventPosition(e);
 draw(p);
}, false);

事件发生时,将事件对象的坐标传给draw办法处置。这里还需要对draw办法做一些小改动:

复制代码

代码如下:

function draw(p){
 var who = [];
 ctx.clearRech(0, 0, cvs.width, cvs.height);
 arr.forEach(function(v, i){
   ctx.beginPath();
   ctx.rect(v.x, v.y, v.width, v.height);
   ctx.stroke();
   if(p && ctx.isPointInPath(p.x, p.y)){
     //假如传入了事件坐标,就用isPointInPath推断一下
     //假如当前环境覆盖了该坐标,就将当前环境的index值放到数组里
     who.push(i);
   }
 });
 //按照数组中的index值,可以到arr数组中寻到响应的元素。
 return who;
}

在上面代码中,点击事件发生时draw办法会施行一次重绘,并在重绘历程中检查每一个图形可否覆盖了事件坐标,假如推断为真,则视为点击了该图形,并将该图形的index值放入数组,最后将数组作为draw办法的返回值。在这种处置机制下,假如Canvas里有N个图形,它们有一部分是重叠的,而点击事件刚巧发生在这个重叠区域上,那么draw办法的返回数组里会有N个成员。这时就有点相似事件冒泡的状况,数组的最后一个成员处于Canvas最上层,而第一个成员则在最基层,我们可以视为最上层的成员是e.target,而其他成员则是冒泡历程中传递到的节点。当然这只是最简便的一种处置办法,假如真要模拟DOM处置,还要给图形设定父子级关系。

以上就是Canvas事件处置的根本办法。在实际使用时,怎样缓存图形参数,怎样停止轮回重绘,乃至怎样处置事件冒泡,都还需要按照实际状况花一些心思去处置。别的,click是一个比力好处置的事件,相对费事的是mou搜索引擎优化ver、mou搜索引擎优化ut和mousemove这些事件,由于鼠标一旦进入Canvas元素,始终发生的都是mousemove事件,所以假如要给某个图形独自设定mou搜索引擎优化ver或mou搜索引擎优化ut,还需要记载鼠标移动的道路,给图形设定进出状态。由于处置的步骤变得复杂起来,必需对机能问题提高关注。

以上就是HTML5 Canvas的事件处置介绍的具体内容,更多请关注百分百源码网其它相关文章!

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有150人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板