Add onclick and onmouseover to canvas element(将 onclick 和 onmouseover 添加到画布元素)
问题描述
我想将 onclick
、onmouseover
和 onmouseout
事件添加到画布元素中的各个形状.
I want to add an onclick
, onmouseover
and an onmouseout
events to individual shapes in a canvas element.
我曾尝试以不同的方式使用 SVG 进行此操作,但发现没有一种方法适用于所有主要浏览器.
I have tried doing this with SVG in different ways and found no single method will work in all the major browsers.
也许,有没有一种简单的方法可以将 onclick
和可能的其他事件添加到画布形状?
Maybe, is there a simple way to add an onclick
and probably other events to canvas shapes?
有人可以告诉我如何添加 onclick
吗?
Can someone please show me how to add an onclick
?
这是我的代码:
canvas
{
background:gainsboro;
border:10px ridge green;
}
<canvas id="Canvas1"></canvas>
var c=document.getElementById("Canvas1");
var ctx=c.getContext("2d");
ctx.fillStyle="blue";
ctx.fillRect(10,10,60,60);
var ctx=c.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(80,60,60,60);
// these need an onclick to fire them up. How do I add the onclick
function blue()
{
alert("hello from blue square")
}
function red()
{
alert("hello from red square")
}
推荐答案
这是一个用于将事件添加到各个画布形状的准系统框架
这是一个预览:http://jsfiddle.net/m1erickson/sAFku/
与 SVG 不同,在画布上绘制形状后,无法识别该形状.
Unlike SVG, after you draw a shape to canvas, there is no way to identify that shape.
在画布上,没有单独的形状,只有一个充满像素的画布.
On canvas, there are no individual shapes, there is just a canvas full of pixels.
为了能够识别和使用"任何单独的画布形状,您需要记住该形状的所有基本属性.
To be able to identity and "use" any individual canvas shape, you need to remember all basic properties of that shape.
以下是识别矩形所需的属性:
Here are the properties necessary to identify a rectangle:
- x 位置,
- y 位置,
- 宽度,
- 身高.
您还需要记住矩形的一些基本样式属性:
You will also want to remember some basic styling properties of a rectangle:
- 填充颜色,
- 描边颜色,
- 笔画宽度.
所以这里是如何创建一个矩形类"对象,它可以记住它自己的所有基本属性.
So here is how to create a rectangle "class" object that remembers all of it’s own basic properties.
如果您不熟悉类"一词,请将其视为我们可以用来定义形状的千篇一律".
If you're not familiar with the term "class", think of it as a "cookie-cutter" that we can use to define a shape.
然后我们可以使用cookie-cutter"类来创建该形状的多个副本.
Then we can use the "cookie-cutter" class to create multiple copies of that shape.
更好 ...类足够灵活,可以让我们修改我们制作的每个副本的基本属性.
Even better ... classes are flexible enough to let us modify the basic properties of each copy that we make.
对于矩形,我们可以使用我们的一个类来制作许多不同宽度、高度、颜色和位置的矩形.
For rectangles, we can use our one class to make many, many rectangles of different widths, heights, colors and locations.
这里的关键是我们创建类,因为类非常灵活且可重用!
The key here is that we create classes because classes are Very Flexible and Reusable!
这是我们的 rect 类,它记住"任何自定义矩形的所有基本信息.
Here is our rect class that "remembers" all the basic info about any custom rectangle.
// 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;
}
我们可以重用这个类来创建我们需要的任意数量的新矩形...并且我们可以为我们的新矩形分配不同的属性以满足我们对多样性的需求.
We can reuse this class to create as many new rectangles as we need...And we can assign different properties to our new rectangles to meet our needs for variety.
当您创建一个实际的矩形时(通过填充它的属性),我们类的每个千篇一律"的副本都有自己的私有属性集.
When you create an actual rectangle (by filling in it's properties), every "cookie-cutter" copy of our class has its own private set of properties.
当我们使用cookie-cutter"类创建 1+ 个实际矩形以在画布上绘制时,生成的真实矩形称为对象".
When we use a "cookie-cutter" class to create 1+ actual rectangles to draw on the canvas, the resulting real rectangles are called "objects".
在这里,我们从 1 个类中创建了 3 个真实的矩形对象.我们为每个真实对象分配了不同的宽度、高度和颜色.
Here we create 3 real rectangle objects from our 1 class. We have assigned each real object different width, height and colors.
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() 函数让我们的类能够在画布上绘制自己.这是我们放置画布上下文绘图命令和样式命令的地方.
Now let’s give our class the ability to draw itself on the canvas by adding a draw() function. This is where we put the canvas context drawing commands and styling commands.
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 个矩形.
Here’s how to use the draw() function to draw rectangles on the canvas. Notice that we have 2 rectangle objects and we must execute .draw() on both of them for 2 rects to show on the canvas.
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() 函数来测试鼠标当前是否在我们的矩形内.
Now give the rect class the ability to let us know if a point (mouse) is inside that rect. When the user generates mouse events, we will use this isPointInside() function to test if the mouse is currently inside our rect.
// 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 类绑定到正常的浏览器鼠标事件系统中.
Finally we can tie our rect class into the normal browser mouse event system.
我们要求 jQuery 监听画布上的鼠标点击.然后我们将该鼠标位置提供给 rect 对象.我们使用矩形的 isPointInside() 来报告点击是否在矩形内.
We ask jQuery to listen for mouse clicks on the canvas. Then we feed that mouse position to the rect object. We use the rect's isPointInside() to report back if the click was inside the rect.
// 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;
嗯...这就是您记住"画布形状和您如何执行问题中的代码!
Well...that's how you "remember" canvas shapes & how you execute the code in your question!
alert("hello from blue square")
这是一个准系统类",可以创建各种矩形并报告鼠标点击.
That’s a barebones "class" that creates various rectangles and reports mouseclicks.
您可以使用此模板作为起点来侦听各种画布形状上的所有鼠标事件.
You can use this template as a starting point to listen for all mouse-events on all kinds of canvas shapes.
几乎所有的画布形状都是矩形或圆形.
Almost all canvas shapes are either rectangular or circular.
矩形画布元素
- 矩形
- 图片
- 文字
- 行(是的!)
圆形画布元素
- 圈子
- 弧线
- 正多边形(是的!)
不规则画布元素
- 曲线(三次和四边形贝塞尔曲线)
- 路径
isPointInside() 看起来像这样:
The isPointInside() would look like this for a circle:
// 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,但这通常会变得复杂!
Even irregularly shaped canvas elements can have isPointInside, but that usually gets complicated!
就是这样!
这里是稍微增强的代码和一个 Fiddle:http://jsfiddle.net/m1erickson/sAFku/
Here is slightly enhanced code and a Fiddle: 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>
这篇关于将 onclick 和 onmouseover 添加到画布元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!