搜索
首页web前端H5教程关于HTML5 Canvas的事件处理

关于HTML5 Canvas的事件处理

Jun 22, 2018 pm 02:31 PM
canvashtml5事件处理

这篇文章主要介绍了HTML5 Canvas的事件处理介绍,本文讲解了Canvas的限制、给Canvas元素绑定事件、isPointInPath方法、循环重绘和事件冒泡等内容,需要的朋友可以参考下

DOM是Web前端领域非常重要的组成部分,不仅在处理HTML元素时会用到DOM,图形编程也同样会用到。比如SVG绘图,各种图形都是以DOM节点的形式插入到页面中,这就意味着可以使用DOM方法对图形进行操作。比如有一个c0c94b330d906535844b10fba4c88182元素,可以直接用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是一个比较好处理的事件,相对麻烦的是mouseover、mouseout和mousemove这些事件,由于鼠标一旦进入Canvas元素,始终发生的都是mousemove事件,所以如果要给某个图形单独设置mouseover或mouseout,还需要记录鼠标移动的路线,给图形设置进出状态。由于处理的步骤变得复杂起来,必须对性能问题提高关注。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

HTML5 canvas学习的实例介绍

angularJS结合canvas画图的实现

以上是关于HTML5 Canvas的事件处理的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
H5:网络标准和技术的发展H5:网络标准和技术的发展Apr 15, 2025 am 12:12 AM

Web标准和技术从HTML4、CSS2和简单的JavaScript演变至今,经历了显着的发展。 1)HTML5引入了Canvas、WebStorage等API,增强了Web应用的复杂性和互动性。 2)CSS3增加了动画和过渡功能,使页面效果更加丰富。 3)JavaScript通过Node.js和ES6的现代化语法,如箭头函数和类,提升了开发效率和代码可读性,这些变化推动了Web应用的性能优化和最佳实践的发展。

H5是HTML5的速记吗?探索细节H5是HTML5的速记吗?探索细节Apr 14, 2025 am 12:05 AM

H5不仅仅是HTML5的简称,它代表了一个更广泛的现代网页开发技术生态:1.H5包括HTML5、CSS3、JavaScript及相关API和技术;2.它提供更丰富、互动、流畅的用户体验,能在多设备上无缝运行;3.使用H5技术栈可以创建响应式网页和复杂交互功能。

H5和HTML5:网络开发中常用的术语H5和HTML5:网络开发中常用的术语Apr 13, 2025 am 12:01 AM

H5与HTML5指的是同一个东西,即HTML5。HTML5是HTML的第五个版本,带来了语义化标签、多媒体支持、画布与图形、离线存储与本地存储等新功能,提升了网页的表现力和交互性。

H5指的是什么?探索上下文H5指的是什么?探索上下文Apr 12, 2025 am 12:03 AM

H5referstoHTML5,apivotaltechnologyinwebdevelopment.1)HTML5introducesnewelementsandAPIsforrich,dynamicwebapplications.2)Itsupportsmultimediawithoutplugins,enhancinguserexperienceacrossdevices.3)SemanticelementsimprovecontentstructureandSEO.4)H5'srespo

H5:工具,框架和最佳实践H5:工具,框架和最佳实践Apr 11, 2025 am 12:11 AM

H5开发需要掌握的工具和框架包括Vue.js、React和Webpack。1.Vue.js适用于构建用户界面,支持组件化开发。2.React通过虚拟DOM优化页面渲染,适合复杂应用。3.Webpack用于模块打包,优化资源加载。

HTML5的遗产:当前了解H5HTML5的遗产:当前了解H5Apr 10, 2025 am 09:28 AM

HTML5hassignificantlytransformedwebdevelopmentbyintroducingsemanticelements,enhancingmultimediasupport,andimprovingperformance.1)ItmadewebsitesmoreaccessibleandSEO-friendlywithsemanticelementslike,,and.2)HTML5introducednativeandtags,eliminatingthenee

H5代码:可访问性和语义HTMLH5代码:可访问性和语义HTMLApr 09, 2025 am 12:05 AM

H5通过语义化元素和ARIA属性提升网页的可访问性和SEO效果。1.使用、、等元素组织内容结构,提高SEO。2.ARIA属性如aria-label增强可访问性,辅助技术用户可顺利使用网页。

H5与HTML5相同吗?H5与HTML5相同吗?Apr 08, 2025 am 12:16 AM

"h5"和"HTML5"在大多数情况下是相同的,但它们在某些特定场景下可能有不同的含义。1."HTML5"是W3C定义的标准,包含新标签和API。2."h5"通常是HTML5的简称,但在移动开发中可能指基于HTML5的框架。理解这些区别有助于在项目中准确使用这些术语。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器