让canvas 支持事件

了解canvas这个标签后,会发现在一个canvas类似一个img图片,在canvas中绘制的图形都是一个整体,所有的事件也都是发生在这一个标签上,没有办法直接判断事件是发生在canvas中的某个图形上。但是通过canvas中的路径的概念可以解决这个问题。

关键:通过路径来绘制图形,用每一个图形是一个路径,事件绑定在canvas标签上,获得事件的发生的x,y坐标。再通过 isPointInPath(),来判断点(x,y)是否在路径内,需要注意的是isPointInPath()只对当前路径(currentPath) 有效,并且经测试发现,只对当前路径的第一个子路径有效(subPath,一个currentPath可以有多个subPath)。关于路径的详细解释可 以看看canvas的api文档。
具体的判断就是,当事件触发时,对canvas中的内容进行重绘,每重回一个路径中的图形,用 isPointInPath()判断一次,如果在路径内,执行相应的操作。

如下面的例子,可以拖动一个canvas标签中绘制的多个圆中的任一个。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >

<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<script type="text/javascript">
	var list=[];
	var currentC;
	var _e={};
    var cricle = function(x,y,r){
    	this.x=x;
    	this.y=y;
    	this.r=r;
    	this.isCurrent=false;
    	this.drawC=function(ctx,x,y){
    		ctx.save();
    		ctx.beginPath();
    		ctx.moveTo(this.x,this.y-this.r);
			ctx.arc(this.x,this.y,this.r,2*Math.PI,0,true);
			if ((x && y && ctx.isPointInPath(x, y) && !currentC )||this.isCurrent) {

					
					ctx.fillStyle = '#ff0000';
					currentC=this;
					this.isCurrent=true;

			}else{
				ctx.fillStyle = '#999999';
			}
			ctx.fill();
    	}
    
    }
	function draw(){
		var canvas = document.getElementById('tutorial');
		if (canvas.getContext){
			var ctx = canvas.getContext('2d');
			for(var i=0;i<10;i++){
				var c=new cricle(20*i,20*i,5*i);
				c.drawC(ctx);
				list.push(c);
			}
		}
	}
	
	function reDraw(e){
		e=e||event;
		var canvas = document.getElementById('tutorial');
		var x = e.clientX - canvas.offsetLeft;
		var y = e.clientY - canvas.offsetTop;

		canvas.width = canvas.width;
		if (canvas.getContext){
			var ctx = canvas.getContext('2d');
			for(var i=0;i<list.length;i++){
				var c=list[i];
				c.drawC(ctx,x,y);

				
			}
		}
	
	}
	
	function show(e){
		e=e||event;
		var canvas = document.getElementById('tutorial');
		var ctx = canvas.getContext('2d');
		var x = e.clientX - canvas.offsetLeft;
		var y = e.clientY - canvas.offsetTop;

		if(currentC){
			currentC.x=parseInt(x+(x-currentC.x)/5);
			currentC.y=parseInt(y+(y-currentC.y)/5);
		}
		_e=e;


	}

	window.οnlοad=function(){
		
		var canvas = document.getElementById('tutorial');
		draw();
		
		canvas.οnmοusedοwn=function(e){
			e=e||event;
			var x = e.clientX - canvas.offsetLeft;
			var y = e.clientY - canvas.offsetTop;
			if(currentC)
				currentC.isCurrent=false;
			currentC=null;
			reDraw(e);
			_e=e;
			var showTimer=setInterval(function(e){
				reDraw(e);
			},10,_e);
			canvas.οnmοusemοve=show;

			document.οnmοuseup=function(){
				if(currentC)
					currentC.isCurrent=false;
				currentC=null;
				canvas.οnmοusemοve=null;
				clearInterval(showTimer);
			}

		}
	}
</script>
<style type="text/css">
  canvas { border: 1px solid black; }
</style>
</head>
<body style="background:#eeeeee;">
	<div style="background:#0f0;width:100px;height:100px;position:absolute;left:100px;top:100px;z-index:1;" οnclick="alert(1);"></div>
    <canvas id="tutorial" width="1000" height="550" style="z-index:100;display:block;position:absolute;"></canvas>
	
</body>
<script>

</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值