我想将onclickonmouseoveronmouseout事件添加到 Canvas 元素中的各个形状。

我尝试以不同的方式对SVG进行此操作,但发现没有一种方法可以在所有主要浏览器中使用。

也许,有没有一种简单的方法可以向 Canvas 形状添加onclick和其他事件?

有人可以告诉我如何添加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")
}

最佳答案

这是一个准系统框架,用于将事件添加到各个 Canvas 形状

这里是预览:http://jsfiddle.net/m1erickson/sAFku/

与SVG不同,在 Canvas 上绘制形状后,无法识别该形状。

在 Canvas 上,没有单独的形状,只有一个充满像素的 Canvas 。

为了能够识别和“使用”任何单独的 Canvas 形状,您需要记住该形状的所有基本属性。

这是识别矩形所必需的属性:

  • x-position,
  • y位置,
  • 宽度,
  • 的高度。

  • 您还需要记住矩形的一些基本样式属性:
  • fillcolor,
  • strokecolor,
  • strokewidth。

  • 因此,这是创建矩形“类”对象并记住其所有基本属性的方法。

    如果您不熟悉“类”一词,可以将其视为可以用来定义形状的“千篇一律”。

    然后,我们可以使用“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切割器”副本都有其自己的私有(private)属性集。

    当我们使用“Cookie-Cutter”类创建1个以上要在 Canvas 上绘制的实际矩形时,所得的实际矩形称为“对象”。

    在这里,我们从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);
    

    现在,让我们的类(class)能够通过添加draw()函数在 Canvas 上绘制自身。这是我们放置 Canvas 上下文绘制命令和样式命令的地方。
    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()函数在 Canvas 上绘制矩形的方法。注意,我们有2个矩形对象,并且必须在两个对象上都执行.draw()才能使2个矩形显示在 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()函数测试鼠标当前是否在我们的矩形内。
    // 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类绑定(bind)到普通的浏览器鼠标事件系统中。

    我们要求jQuery侦听 Canvas 上的鼠标单击。然后,我们将该鼠标位置输入到rect对象。如果点击是在rect内部,我们将使用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;
    

    好吧...这就是您“记住” Canvas 形状以及如何执行问题代码的方式!
    alert("hello from blue square")
    

    这是一个准系统“类”,它创建各种矩形并报告鼠标单击。

    您可以使用此模板作为起点来侦听各种 Canvas 形状上的所有鼠标事件。

    几乎所有的 Canvas 形状都是矩形或圆形。

    矩形 Canvas 元素
  • 矩形
  • 图片
  • 文字
  • 行(是!)

  • 圆形 Canvas 元素
  • 常规多边形(是!)

  • 不规则 Canvas 元素
  • 曲线(三次方和四方贝塞尔曲线)
  • 路径

  • 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 );
    }
    

    即使形状不规则的 Canvas 元素也可以具有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>
    

    关于javascript - 将onclick和onmouseover添加到 Canvas 元素,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16628184/

    10-16 19:58