get click event of each rectangle inside canvas?

后端 未结 5 1116
说谎
说谎 2020-12-01 08:31

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

here is the sample:

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

相关标签:
5条回答
  • 2020-12-01 08:55

    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;
    } 
    
    0 讨论(0)
  • 2020-12-01 09:07

    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);
    }
    
    0 讨论(0)
  • 2020-12-01 09:11

    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.

    0 讨论(0)
  • 2020-12-01 09:12

    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/

    0 讨论(0)
  • 2020-12-01 09:17

    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/

    0 讨论(0)
提交回复
热议问题