这是一个准系统框架,用于将事件添加到各个画布形状
这是一个预览:http: //jsfiddle.net/m1erickson/sAFku/
与 SVG 不同,在画布上绘制形状后,无法识别该形状。
在画布上,没有单独的形状,只有一个充满像素的画布。
为了能够识别和“使用”任何单独的画布形状,您需要记住该形状的所有基本属性。
以下是识别矩形所需的属性:
您还需要记住矩形的一些基本样式属性:
所以这里是如何创建一个矩形“类”对象来记住它自己的所有基本属性。
如果您不熟悉术语“类”,请将其视为我们可以用来定义形状的“千篇一律”。
然后我们可以使用“cookie-cutter”类来创建该形状的多个副本。
更好的是......类足够灵活,可以让我们修改我们制作的每个副本的基本属性。
对于矩形,我们可以使用我们的一个类来制作许多不同宽度、高度、颜色和位置的矩形。
这里的关键是我们创建类,因为类非常灵活且可重用!
这是我们的 rect 类,它“记住”任何自定义矩形的所有基本信息。
// the rect class
function rect(id,x,y,width,height,fill,stroke,strokewidth) {
this.x=x;
this.y=y;
this.id=id;
this.width=width;
this.height=height;
this.fill=fill||"gray";
this.stroke=stroke||"skyblue";
this.strokewidth=strokewidth||2;
}
我们可以重用这个类来创建我们需要的任意数量的新矩形......并且我们可以为我们的新矩形分配不同的属性以满足我们对多样性的需求。
当你创建一个实际的矩形时(通过填充它的属性),我们类的每个“千篇一律”的副本都有自己的私有属性集。
当我们使用“cookie-cutter”类创建 1+ 个实际矩形以在画布上绘制时,生成的真实矩形称为“对象”。
在这里,我们从 1 个类中创建了 3 个真实的矩形对象。我们为每个真实对象分配了不同的宽度、高度和颜色。
var myRedRect = new rect("Red-Rectangle",15,35,65,60,"red","black",3);
var myGreenRect = new rect("Green-Rectangle",115,55,50,50,"green","black",3);
var myBlueRect = new rect("Blue-Rectangle",215,95,25,20,"blue","black",3);
现在让我们通过添加 draw() 函数让我们的类能够在画布上绘制自己。这是我们放置画布上下文绘图命令和样式命令的地方。
rect.prototype.draw(){
ctx.save();
ctx.beginPath();
ctx.fillStyle=this.fill;
ctx.strokeStyle=this.stroke;
ctx.lineWidth=this.strokewidth;
ctx.rect(x,y,this.width,this.height);
ctx.stroke();
ctx.fill();
ctx.restore();
}
下面介绍如何使用 draw() 函数在画布上绘制矩形。请注意,我们有 2 个矩形对象,我们必须对它们执行 .draw() 以在画布上显示 2 个矩形。
var myRedRect = new rect("Red-Rectangle",15,35,65,60,"red","black",3);
myRedRect.draw();
var myBlueRect = new rect("Blue-Rectangle",125,85,100,100,"blue","orange",3);
myBlueRect.draw();
现在让 rect 类能够让我们知道一个点(鼠标)是否在该矩形内。当用户生成鼠标事件时,我们将使用这个 isPointInside() 函数来测试鼠标当前是否在我们的矩形内。
// accept a point (mouseposition) and report if it’s inside the rect
rect.prototype.isPointInside = function(x,y){
return( x>=this.x
&& x<=this.x+this.width
&& y>=this.y
&& y<=this.y+this.height);
}
最后,我们可以将 rect 类绑定到正常的浏览器鼠标事件系统中。
我们要求 jQuery 监听画布上的鼠标点击。然后我们将该鼠标位置提供给 rect 对象。我们使用矩形的 isPointInside() 来报告点击是否在矩形内。
// listen for click events and trigger handleMouseDown
$("#canvas").click(handleMouseDown);
// calc the mouseclick position and test if it's inside the rect
function handleMouseDown(e){
// calculate the mouse click position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// test myRedRect to see if the click was inside
if(myRedRect.isPointInside(mouseX,mouseY)){
// we (finally!) get to execute your code!
alert("Hello from the "+myRedRect.id);
}
}
// These are the canvas offsets used in handleMouseDown (or any mouseevent handler)
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
嗯......这就是你如何“记住”画布形状以及如何执行问题中的代码!
alert("hello from blue square")
这是一个创建各种矩形并报告鼠标点击的准系统“类”。
您可以使用此模板作为起点来侦听各种画布形状上的所有鼠标事件。
几乎所有的画布形状都是矩形或圆形。
矩形画布元素
圆形画布元素
不规则画布元素
圆的 isPointInside() 看起来像这样:
// check for point inside a circlular shape
circle.prototype.isPointInside = function(x,y){
var dx = circleCenterX-x;
var dy = circleCenterY-y;
return( dx*dx+dy*dy <= circleRadius*circleRadius );
}
即使是不规则形状的画布元素也可以有 isPointInside,但这通常会变得复杂!
而已!
这是稍微增强的代码和小提琴:http: //jsfiddle.net/m1erickson/sAFku/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
//
var rect = (function () {
// constructor
function rect(id,x,y,width,height,fill,stroke,strokewidth) {
this.x=x;
this.y=y;
this.id=id;
this.width=width;
this.height=height;
this.fill=fill||"gray";
this.stroke=stroke||"skyblue";
this.strokewidth=strokewidth||2;
this.redraw(this.x,this.y);
return(this);
}
//
rect.prototype.redraw = function(x,y){
this.x=x;
this.y=y;
ctx.save();
ctx.beginPath();
ctx.fillStyle=this.fill;
ctx.strokeStyle=this.stroke;
ctx.lineWidth=this.strokewidth;
ctx.rect(x,y,this.width,this.height);
ctx.stroke();
ctx.fill();
ctx.restore();
return(this);
}
//
rect.prototype.isPointInside = function(x,y){
return( x>=this.x
&& x<=this.x+this.width
&& y>=this.y
&& y<=this.y+this.height);
}
return rect;
})();
//
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mousedown stuff here
var clicked="";
for(var i=0;i<rects.length;i++){
if(rects[i].isPointInside(mouseX,mouseY)){
clicked+=rects[i].id+" "
}
}
if(clicked.length>0){ alert("Clicked rectangles: "+clicked); }
}
//
var rects=[];
//
rects.push(new rect("Red-Rectangle",15,35,65,60,"red","black",3));
rects.push(new rect("Green-Rectangle",60,80,70,50,"green","black",6));
rects.push(new rect("Blue-Rectangle",125,25,10,10,"blue","black",3));
//
$("#canvas").click(handleMouseDown);
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>