0
点赞
收藏
分享

微信扫一扫

Canvas 入门3 Click事件处理

传统的DOM的事件处理机制在Canvas里并不适应.Canvas是一个整体,无法给里面的某个图形增加Javascript事件。

由于事件只能达到Canvas元素这一层,所以,如果要识别点击发生在哪一个图形上,需要增加代码进行处理:

  • 给Canvas绑定事件
  • 事件发生时,检查事件对象的位置
  • 检查哪些图形覆盖了该位置

给Canvas元素绑定事件

cvs = document.getElementById('canvas');
cvs.addEventListener('click,function(e){

},false);

判断事件对象发生的位置

事件对象e的.layerX和layerY属性代表Canvas内部坐标系中的坐标。但这个属性可能会被废弃,所以要写兼容方法:

//该函数需要将canvas的position设置为absolute
<canvas id="myCanvas" width="400" height="400" style="border:2px solid #eee;position:absolute"></canvas>

<script>
var cvs = document.getElementById('myCanvas');
cvs.addEventListener('click',function(e){
console.log(getEventPosition(e));
},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};
}
</script>

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

事件结合isPointInPath

<canvas id="myCanvas" width="400" height="400" style="border:2px solid #eee;position:absolute"></canvas>

<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
ctx.rect(10,10,100,100);
ctx.stroke();
console.log(ctx.isPointInPath(50,50));

canvas.addEventListener('click',function(e){
console.log(getEventPosition(e));
var p=getEventPosition(e);
console.log(ctx.isPointInPath(p.x,p.y));
},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};
}

</script>

isPointInPath方法仅判断当前上下文环境中的路径,所以当Canvas里已经绘制了多个图形时,仅能以最后一个图形的上下文环境来判断事件
解决方案:当点击事件发生时,重绘所有图形,每绘制一个就使用isPointInPath方法,判断事件坐标是否在该图形覆盖范围内。

循环重绘和事件冒泡

为了实现循环重绘,要先将图形的基本参数先保存下来。

<body>
<canvas id="mycanvas" width="150" height="150"></canvas>

<script type="text/javascript">
arr = [
  {x:10, y:10, width:100, height:100},
  {x:110, y:110, width:100, height:100}
  ];
var canvas = document.getElementById('mycanvas');
  var ctx = canvas.getContext('2d');
  
  function draw(){
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  arr.forEach(function(v){
  ctx.beginPath();
  ctx.rect(v.x, v.y, v.width, v.height);
  ctx.stroke();
  });
}
draw();
</script>
</body>

实现点击后重绘,并判断点击图形

<body>
<canvas id="mycanvas" width="150" height="150"></canvas>

<script type="text/javascript">
arr = [
  {x:10, y:10, width:100, height:100},
  {x:110, y:110, width:100, height:100}
  ];
var canvas = document.getElementById('mycanvas');
  var ctx = canvas.getContext('2d');
  canvas.addEventListener('click', function(e){
p = getEventPosition(e);
var who=draw(p);
console.log('in',who);
}, false);
  function draw(p){
console.log('click',p);
var who=[];
  ctx.clearRect(0, 0, canvas.width, canvas.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)){
who.push(i);
}
  });
return who;
}
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};
}
draw();
</script>
</body>


举报

相关推荐

0 条评论