canvas教程

HTML5 canvas 内部元素事件响应

字号+ 作者:H5之家 来源:H5之家 2017-10-12 14:13 我要评论( )

HTML5 canvas 内部元素事件响应

Note: 本文的逻辑主体参考自:,但是由于原文有较多小错误且没有最终代码,本文将之改正,添加了一个实例并添加了最终的实现代码,算作改进版吧。

最近做一个项目,需要在页面上画一个小人,然后点击小人的不同部分响应不同的位置。例如,点击左腿,显示“点击的是左腿”,点击右腿,显示“点击的是右腿”。因为项目使用的HTML5,所以理所应当的想到了用canvas来画这个小人,但是发现canvas对象是作为一个整体存在的。也就是说, 图形本身实际都是Canvas的一部分,不可单独获取,所以也就无法直接给某个图形增加JavaScript 事件。这样,如果想点击小人的左腿,是点击不到的,你点击的是canvas的整个对象。

给Canvas元素绑定事件

”由于事件只能达到Canvas元素这一层,所以,如果想进一步深入,识别点击发生在Canvas内部的哪一个图形上,就需要增加代码来进行处理。基本思路是:给Canvas元素绑定事件,当事件发生时,检查事件对象的位置,然后检查哪些图形覆盖了该位置。例如 一个矩形,该矩形覆盖x轴10-110、y轴10-110的范围。只要鼠标点击在这个范围里,就可以视为点击了该矩形,也就可以手动触发矩形需要处理的点击事件。思路其实比较简单,但是实现起来还是稍微有点复杂。不仅要考虑这个判断过程的效率,有些地方还需要重新判断事件类型,设置要重新定义一个Canvas内部的捕获和冒泡机制。”

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

canvas = document.getElementById('myCanvas'); canvas .addEventListener('click', function(e){ //当click时运行 }, 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 = document.getElementById('myCanvas'); ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.rect(10, 10, 100, 100); ctx.fill(); ctx.isPointInPath(50, 50); //true ctx.isPointInPath(5, 5); //false

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

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

为了实现重绘,先画一个小人,然后当点击的时候再重绘小人,每次画一个部分的时候就检查是否点击了此部分,如果点击了,那么将相应的序号保存起来。以下是整个小人的代码。

<!DOCTYPE html> <html> <head> <title>HTML5 Canvas Demo</title> <!--[if IE]> <script type="text/javascript" src="excanvas.js"></script> <![endif]--> <script> //初始时画小人 window.onload=function() { var canvas = document.getElementById('myCanvas'); if (canvas.getContext){ var ctx = canvas.getContext('2d'); //画左边头 ctx.fillStyle='#1c94c4'; ctx.beginPath(); ctx.arc(105,75,35,Math.PI/2,Math.PI*1.5,false); ctx.fill(); //画右边头 ctx.beginPath(); ctx.arc(110,75,35,Math.PI*1.5,Math.PI/2,false); ctx.fill(); //画躯干 ctx.beginPath(); ctx.rect(80,120,55,100); ctx.fill(); //画左臂 ctx.beginPath(); ctx.rect(25,140,50,20); ctx.fill(); //画右臂 ctx.beginPath(); ctx.rect(140,140,50,20); ctx.fill(); //画左腿 ctx.beginPath(); ctx.rect(80,225,20,80); ctx.fill(); //画右腿 ctx.beginPath(); ctx.rect(115,225,20,80); ctx.fill(); //添加事件响应 canvas.addEventListener('click', function(e){ p = getEventPosition(e); reDraw(p,ctx); }, false); } } //得到点击的坐标 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}; } //重绘 function reDraw(p,ctx){ arr = [ {x:105, y:75, width:Math.PI/2, height:Math.PI*1.5}, {x:110, y:75, width:Math.PI*1.5, height:Math.PI/2}, {x:80, y:120, width:55, height:100}, {x:25, y:140, width:50, height:20}, {x:140, y:140, width:50, height:20}, {x:80, y:225, width:20, height:80}, {x:115, y:225, width:20, height:80} ] //保存序号的数组,这样,即使一次点多个,也能保存——本例中只能每次点一个 var whichObject = []; for(var i=0; i < arr.length; i++){ //用圆画头 if(i<2){ ctx.fillStyle='#1c94c4'; ctx.beginPath(); ctx.arc(arr[i].x,arr[i].y,35,arr[i].width,arr[i].height,false); ctx.fill(); if(p && ctx.isPointInPath(p.x, p.y)){ whichObject.push(i); //修改点中区域的颜色 ctx.fillStyle='#F39814'; ctx.beginPath(); ctx.arc(arr[i].x,arr[i].y,35,arr[i].width,arr[i].height,false); ctx.fill(); } //用矩形画躯干 }else{ ctx.fillStyle='#1c94c4'; ctx.beginPath(); ctx.rect(arr[i].x,arr[i].y, arr[i].width,arr[i].height); ctx.fill(); if(p && ctx.isPointInPath(p.x, p.y)){ whichObject.push(i); ctx.fillStyle='#F39814'; ctx.beginPath(); ctx.rect(arr[i].x,arr[i].y, arr[i].width,arr[i].height); ctx.fill(); } } } //显示点击了哪个部分 //alert("click:" + whichObject[0]); } </script> </head> <body> <div style="margin-left:30px;"> <canvas id="myCanvas" width="600" height="500" style="border: 5px blue solid"></canvas> <br /><br /> </div> </body> </html>

 另:推荐几个快速学习canvas的网址:

Canvas教程: https://developer.mozilla.org/zh-CN/docs/Canvas_tutorial

使用html5 canvas绘制精美图形:

Canvas图形事件的另一个实例:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • html5 canvas消除锯齿

    html5 canvas消除锯齿

    2017-10-12 15:01

  • Canvas Canvas骰子

    Canvas Canvas骰子

    2017-10-11 18:00

  • [js妙手之路] html5 canvas教程

    [js妙手之路] html5 canvas教程

    2017-10-11 17:08

  • canvas getContext对象方法和属性详细介绍

    canvas getContext对象方法和属性详细介绍

    2017-10-11 14:03

网友点评
i