HTML5画布:找出点击坐标是否在给定的矩形内

ekh*_*led 5 javascript events canvas

可能有些人在这个困境中有类似的经历,可以帮助我在这里......

基本上,我有一个canvas元素,我在其中使用循环绘制几个矩形

context.fillRect (x, y, width, height)
Run Code Online (Sandbox Code Playgroud)

现在,我希望一些矩形成为热点并响应点击事件.我可以使用event.layerX和找出单击事件的确切(x,y)event.layerY.

鉴于我知道以下内容:

  • 点击的确切x,y
  • 每个矩形的x,y,宽度和高度

如何确定点击事件是否发生在周边某个矩形内
并且,
click事件发生在哪个矩形0n?

有没有像这样的数学公式?

任何帮助将不胜感激,如果我不够清楚,请告诉我......

谢谢

编辑
没有比绕过所有矩形并检查它们的位置和尺寸更好的方法吗?

小智 13

这是使用地图时经常遇到的一般拓扑问题.

决定点是否在任何多边形(矩形,圆形,不规则形状)内的算法如下:

  • 从被检查的点开始构造任何方向上的任何线,直到您的多边形所在的屏幕区域的边缘

  • 如果该线与奇数个位置处的任何多边形边界相交,则它该多边形内

  • 如果该线与任何多边形边界相交,则它该多边形之外偶数个位置.

           ------------
           |           |
           |        o--|-------------------    1 intersection: inside
           |           |
           -------------
           ------------
           |           |
    o------|-----------|-------------------    2 intersections: outside
           |           |
           -------------
    
    Run Code Online (Sandbox Code Playgroud)

笔记:

  • 线的方向是无关紧要的

  • 如果在没有关闭的情况下在屏幕侧面切割多边形,则无法工作

  • 如果多边形切割自身,那么如果线恰好通过切割点,则算法可能会失败(例如,在图8中,线被视为单个多边形,其中线正好穿过图中的上部和下部连接处连接)


pra*_*uss 5

我讨厌在这里发布大量的代码,但是这里有一个可以帮助你的js类......

function Point(x,y){
    this.x=x;
    this.y=y;
}

function Polygon(){
    this.points=[];
    this.x_min=undefined;
    this.x_max=undefined;
    this.y_min=undefined;
    this.y_max=undefined;

    this.add = function(p){
        this.points=this.points.concat(p);
        if (p.x<this.x_min){this.x_min=p.x;}
        if (p.x>this.x_max){this.x_max=p.x;}
        if (p.y<this.y_min){this.y_min=p.y;}
        if (p.y>this.y_min){this.y_max=p.y;}
    }

    this.pointInPoly = function(p){
        var j=(this.points.length-1);  //start by testing the link from the last point to the first point
        var isOdd=false;

        //check the bounding box conditions
        if (p.x < this.x_min || p.x > this.x_max || p.y < this.y_min || p.y > this.y_max){
            return false;
        }

        //if necessary use the line crossing algorithm
        for(var i=0; i<this.points.length; i++){
            if ((this.points[i].y<p.y && this.points[j].y>=p.y) ||  
                (this.points[j].y<p.y && this.points[i].y>=p.y)) {
                    if (this.points[i].x+(p.y-this.points[i].y)/(this.points[j].y-
                        this.points[i].y)*(this.points[j].x-this.points[i].x)<p.x)
                    { isOdd=(!isOdd);} }
            j=i;
        }
        return isOdd;
    }
}
Run Code Online (Sandbox Code Playgroud)

PS:您需要使用以下函数将您的点击事件转换为本地坐标(其中e是您的点击事件):

function getPosition(e){
    var p = new Point();
    if (e.pageX != undefined && e.pageY != undefined) {
        p.x = e.pageX;
        p.y = e.pageY;
     }
     else {
        p.x = e.clientX + document.body.scrollLeft +
                document.documentElement.scrollLeft;
        p.y = e.clientY + document.body.scrollTop +
                document.documentElement.scrollTop;
    }
    p.x -= gCanvas.offsetLeft;
    p.y -= gCanvas.offsetTop;


    return p;
}
Run Code Online (Sandbox Code Playgroud)