获取画布内每个矩形的单击事件?

发布于 2024-10-17 09:33:42 字数 138 浏览 1 评论 0 原文

我不知道如何在每个矩形上注册单击事件。

这是示例:

http://jsfiddle.net/9WWqG/1/

I dont know how to register click event on each rectangle.

here is the sample:

http://jsfiddle.net/9WWqG/1/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

远昼 2024-10-24 09:33:42

您基本上必须跟踪矩形在画布上的位置,然后在画布本身上设置一个事件侦听器。从那里您可以获取单击事件的坐标并遍历所有矩形以测试“碰撞”。

下面是这样做的一个示例: http://jsfiddle.net/9WWqG/2/

html :

<canvas id="myCanvas" width="300" height="150"></canvas>

javascript:

// get canvas element.
var elem = document.getElementById('myCanvas');

function collides(rects, x, y) {
    var isCollision = false;
    for (var i = 0, len = rects.length; i < len; i++) {
        var left = rects[i].x, right = rects[i].x+rects[i].w;
        var top = rects[i].y, bottom = rects[i].y+rects[i].h;
        if (right >= x
            && left <= x
            && bottom >= y
            && top <= y) {
            isCollision = rects[i];
        }
    }
    return isCollision;
}

// check if context exist
if (elem && elem.getContext) {
    // list of rectangles to render
    var rects = [{x: 0, y: 0, w: 50, h: 50},
                 {x: 75, y: 0, w: 50, h: 50}];
  // get context
  var context = elem.getContext('2d');
  if (context) {

      for (var i = 0, len = rects.length; i < len; i++) {
        context.fillRect(rects[i].x, rects[i].y, rects[i].w, rects[i].h);
      }

  }
    
    // listener, using W3C style for example    
    elem.addEventListener('click', function(e) {
        console.log('click: ' + e.offsetX + '/' + e.offsetY);
        var rect = collides(rects, e.offsetX, e.offsetY);
        if (rect) {
            console.log('collision: ' + rect.x + '/' + rect.y);
        } else {
            console.log('no collision');
        }
    }, false);
}

You're basically going to have to track where your rectangles are on the canvas, then set up an event listener on the canvas itself. From there you can take the coordinates of the click event and go through all your rectangles to test for 'collisions'.

Here's an example of doing just that: http://jsfiddle.net/9WWqG/2/

html:

<canvas id="myCanvas" width="300" height="150"></canvas>

javascript:

// get canvas element.
var elem = document.getElementById('myCanvas');

function collides(rects, x, y) {
    var isCollision = false;
    for (var i = 0, len = rects.length; i < len; i++) {
        var left = rects[i].x, right = rects[i].x+rects[i].w;
        var top = rects[i].y, bottom = rects[i].y+rects[i].h;
        if (right >= x
            && left <= x
            && bottom >= y
            && top <= y) {
            isCollision = rects[i];
        }
    }
    return isCollision;
}

// check if context exist
if (elem && elem.getContext) {
    // list of rectangles to render
    var rects = [{x: 0, y: 0, w: 50, h: 50},
                 {x: 75, y: 0, w: 50, h: 50}];
  // get context
  var context = elem.getContext('2d');
  if (context) {

      for (var i = 0, len = rects.length; i < len; i++) {
        context.fillRect(rects[i].x, rects[i].y, rects[i].w, rects[i].h);
      }

  }
    
    // listener, using W3C style for example    
    elem.addEventListener('click', function(e) {
        console.log('click: ' + e.offsetX + '/' + e.offsetY);
        var rect = collides(rects, e.offsetX, e.offsetY);
        if (rect) {
            console.log('collision: ' + rect.x + '/' + rect.y);
        } else {
            console.log('no collision');
        }
    }, false);
}
临风闻羌笛 2024-10-24 09:33:42

这是一个老问题,但发布时曾经很难做到的事情现在变得容易多了。

有许多库可以跟踪在画布上绘制的对象的位置,并处理处理鼠标交互的所有复杂性。请参阅 EaselJS
KineticJS,
Paper.js
Fabric.js 和这个 画布库比较了解更多信息。

您还可以采取不同的方法并使用
拉斐尔格拉斐尔
拥有一个使用 SVG 和 VML 而不是画布并且甚至可以在 IE6 上运行的解决方案。

您的示例更改为使用 Raphaël 将如下所示:

var r = Raphael(0, 0, 300, 150);

r.rect(0, 0, 50, 50)
    .attr({fill: "#000"})
    .click(function () {
        alert('first rectangle clicked');
     });
    
r.rect(75, 0, 50, 50)
    .attr({fill: "#000"})
    .click(function () {
        alert('second rectangle clicked');
     });

请参阅 DEMO

2015 更新

您也许还可以使用 ART,这是一种用于 HTML5 画布的保留模式矢量绘图 API - 请参阅这个答案< /strong> 了解更多信息。

This is an old question but what was once hard to do when it was posted is now much easier.

There are many libraries that keep track of the position of your objects that were drawn on canvas and handle all of the complexities of handling mouse interactions. See EaselJS,
KineticJS,
Paper.js or
Fabric.js and this comparison of canvas libraries for more.

You can also take a different approach and use
Raphaël and gRaphaël
to have a solution that uses SVG and VML instead of canvas and works even on IE6.

Your example changed to use Raphaël would look like this:

var r = Raphael(0, 0, 300, 150);

r.rect(0, 0, 50, 50)
    .attr({fill: "#000"})
    .click(function () {
        alert('first rectangle clicked');
     });
    
r.rect(75, 0, 50, 50)
    .attr({fill: "#000"})
    .click(function () {
        alert('second rectangle clicked');
     });

See DEMO.

Update 2015

You may also be able to use ART, a retained mode vector drawing API for HTML5 canvas - see this answer for more info.

淡紫姑娘! 2024-10-24 09:33:42

我找到了一种在 mozilla 中使用 clientX,clientY 而不是 offsetX/offsetY 来完成这项工作的方法。

另外,如果您的画布超出 innerHeight 并使用滚动,请将 window.pageYOffset 添加到 e.clientY。如果您的画布超出宽度,则以同样的方式进行。

另一个例子在我的 github 上: https://github.com/michaelBenin/fi-test

这里是另一个解释这一点的链接: http://eli.thegreenplace.net/2010/02/13/finding-out-the-mouse-click-position-on-a-canvas-with-javascript/

I found a way to make this work in mozilla using the clientX,clientY instead of offsetX/offsetY.

Also, if your canvas extends beyond the innerHeight, and uses the scroll, add the window.pageYOffset to the e.clientY. Goes the same way, if your canvas extends beyond the width.

Another example is at my github: https://github.com/michaelBenin/fi-test

Here is another link that explains this: http://eli.thegreenplace.net/2010/02/13/finding-out-the-mouse-click-position-on-a-canvas-with-javascript/

徒留西风 2024-10-24 09:33:42

如果您想在画布中支持多个矩形并处理其单击事件,请使用以下函数以下

<canvas id="myCanvas" width="1125" height="668" style="border: 3px solid #ccc; margin:0;padding:0;" />
  var elem = document.getElementById('myCanvas'),
    elemLeft = elem.offsetLeft,
    elemTop = elem.offsetTop,
    context = elem.getContext('2d'),
    elements = [];

    // Add event listener for `click` events.
    elem.addEventListener('click', function (event) {
       // var leftWidth = $("#leftPane").css("width")

      //  var x = event.pageX - (elemLeft + parseInt(leftWidth) + 220),
       //     y = event.pageY - (elemTop + 15);

            var x = event.pageX - elemLeft,
        y = event.pageY - elemTop;

        elements.forEach(function (element) {
            if (y > element.top && y < element.top + element.height && x > element.left && x < element.left + element.width) {
                alert(element.text);
            }
        });
    }, false);



    // Set the value content (x,y) axis
    var x = 15, y = 20, maxWidth = elem.getAttribute("width"),
        maxHeight = elem.getAttribute("height"), type = 'TL',
        width = 50, height = 60, text = "", topy = 0, leftx = 0;



    for (i = 1; i <= 15; i++) {
        y = 10;
        for (j = 1; j <= 6; j++) {
            width = 50, height = 60
            switch (j) {
                case 1:
                    type = 'TL'; // Trailer
                    height = 60;
                    width = 85;
                    text = i + 'E';
                    break;
                case 2:
                    type = 'DR'; // Door
                    height = 35;
                    width = 85;
                    text = i;
                    break;
                case 3:
                    type = 'FL'; // Floor
                    height = 30;
                    width = 40;
                    break;
                case 4:
                    type = 'FL'; // Floor
                    height = 30;
                    width = 40;
                    y -= 10;
                    break;
                case 5:
                    type = 'DR'; // Door
                    height = 35;
                    width = 85;
                    text = i*10 + 1;
                    y = topy;
                    break;
                case 6:
                    type = 'TL'; // Trailer
                    height = 60;
                    width = 85;
                    text = i + 'F';
                    y += 5;
                    break;
            }

            topy = y;
            leftx = x;
            if (type == 'FL') {
                for (k = 1; k <= 12; k++) {
                    elements.push({
                        colour: '#05EFFF',
                        width: width,
                        height: height,
                        top: topy,
                        left: leftx,
                        text: k,
                        textColour: '#fff',
                        type: type
                    });

                    if (k % 2 == 0) {
                        topy = y + elements[j - 1].height + 5;
                        leftx = x;
                        y = topy;
                    }
                    else {
                        topy = y;
                        leftx = x + elements[j - 1].width + 5;
                    }
                }
                x = leftx;
                y = topy;
            }
            else {
                elements.push({
                    colour: '#05EFFF',
                    width: width,
                    height: height,
                    top: y,
                    left: x,
                    text: text,
                    textColour: '#fff',
                    type: type
                });
            }

            //get the y axis for next content
            y = y + elements[j-1].height + 6
            if (y >= maxHeight - elements[j-1].height) {
                break;
            }
        }
        //get the x axis for next content
        x = x + elements[0].width + 15
        if (x >= maxWidth - elements[0].width) {
            break;
        }
    }

    // Render elements.
    elements.forEach(function (element) {
        context.font = "14pt Arial";
        context.strokeStyle = "#000";
        context.rect(element.left, element.top, element.width, element.height);
        if (element.type == 'FL') {
            context.fillText(element.text, element.left + element.width / 4, element.top + element.height / 1.5);
        }
        else {
            context.fillText(element.text, element.left + element.width / 2.5, element.top + element.height / 1.5);
        }
        context.lineWidth = 1;
        context.stroke()
    });

是执行此操作的示例: http://jsfiddle.net/BmeKr/1291/

Please use below function if you want to support more than one rectangle in canvas and handle its click event

<canvas id="myCanvas" width="1125" height="668" style="border: 3px solid #ccc; margin:0;padding:0;" />
  var elem = document.getElementById('myCanvas'),
    elemLeft = elem.offsetLeft,
    elemTop = elem.offsetTop,
    context = elem.getContext('2d'),
    elements = [];

    // Add event listener for `click` events.
    elem.addEventListener('click', function (event) {
       // var leftWidth = $("#leftPane").css("width")

      //  var x = event.pageX - (elemLeft + parseInt(leftWidth) + 220),
       //     y = event.pageY - (elemTop + 15);

            var x = event.pageX - elemLeft,
        y = event.pageY - elemTop;

        elements.forEach(function (element) {
            if (y > element.top && y < element.top + element.height && x > element.left && x < element.left + element.width) {
                alert(element.text);
            }
        });
    }, false);



    // Set the value content (x,y) axis
    var x = 15, y = 20, maxWidth = elem.getAttribute("width"),
        maxHeight = elem.getAttribute("height"), type = 'TL',
        width = 50, height = 60, text = "", topy = 0, leftx = 0;



    for (i = 1; i <= 15; i++) {
        y = 10;
        for (j = 1; j <= 6; j++) {
            width = 50, height = 60
            switch (j) {
                case 1:
                    type = 'TL'; // Trailer
                    height = 60;
                    width = 85;
                    text = i + 'E';
                    break;
                case 2:
                    type = 'DR'; // Door
                    height = 35;
                    width = 85;
                    text = i;
                    break;
                case 3:
                    type = 'FL'; // Floor
                    height = 30;
                    width = 40;
                    break;
                case 4:
                    type = 'FL'; // Floor
                    height = 30;
                    width = 40;
                    y -= 10;
                    break;
                case 5:
                    type = 'DR'; // Door
                    height = 35;
                    width = 85;
                    text = i*10 + 1;
                    y = topy;
                    break;
                case 6:
                    type = 'TL'; // Trailer
                    height = 60;
                    width = 85;
                    text = i + 'F';
                    y += 5;
                    break;
            }

            topy = y;
            leftx = x;
            if (type == 'FL') {
                for (k = 1; k <= 12; k++) {
                    elements.push({
                        colour: '#05EFFF',
                        width: width,
                        height: height,
                        top: topy,
                        left: leftx,
                        text: k,
                        textColour: '#fff',
                        type: type
                    });

                    if (k % 2 == 0) {
                        topy = y + elements[j - 1].height + 5;
                        leftx = x;
                        y = topy;
                    }
                    else {
                        topy = y;
                        leftx = x + elements[j - 1].width + 5;
                    }
                }
                x = leftx;
                y = topy;
            }
            else {
                elements.push({
                    colour: '#05EFFF',
                    width: width,
                    height: height,
                    top: y,
                    left: x,
                    text: text,
                    textColour: '#fff',
                    type: type
                });
            }

            //get the y axis for next content
            y = y + elements[j-1].height + 6
            if (y >= maxHeight - elements[j-1].height) {
                break;
            }
        }
        //get the x axis for next content
        x = x + elements[0].width + 15
        if (x >= maxWidth - elements[0].width) {
            break;
        }
    }

    // Render elements.
    elements.forEach(function (element) {
        context.font = "14pt Arial";
        context.strokeStyle = "#000";
        context.rect(element.left, element.top, element.width, element.height);
        if (element.type == 'FL') {
            context.fillText(element.text, element.left + element.width / 4, element.top + element.height / 1.5);
        }
        else {
            context.fillText(element.text, element.left + element.width / 2.5, element.top + element.height / 1.5);
        }
        context.lineWidth = 1;
        context.stroke()
    });

Here's an example of doing just that: http://jsfiddle.net/BmeKr/1291/

涙—继续流 2024-10-24 09:33:42

如果你想在画布上支持多个矩形并处理其点击事件,请使用下面的函数......由 Matt King 给出的修改逻辑。

function collides(myRect, x, y) {
    var isCollision = false;
    for (var i = 0, len = myRect.length; i < len; i++) {
        var left = myRect[i].x, right = myRect[i].x+myRect[i].w;
        var top = myRect[i].y, bottom = myRect[i].y+myRect[i].h;
       if ((left + right) >= x
            && left <= x
            && (top +bottom) >= y
            && top <= y) {
            isCollision = json.Major[i];
        }
        }
    }
    return isCollision;
}

Please use below function if you want to support more than one rectangle in canvas and handle its click event..... modified logic given by Matt King.

function collides(myRect, x, y) {
    var isCollision = false;
    for (var i = 0, len = myRect.length; i < len; i++) {
        var left = myRect[i].x, right = myRect[i].x+myRect[i].w;
        var top = myRect[i].y, bottom = myRect[i].y+myRect[i].h;
       if ((left + right) >= x
            && left <= x
            && (top +bottom) >= y
            && top <= y) {
            isCollision = json.Major[i];
        }
        }
    }
    return isCollision;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文