получить событие щелчка каждого прямоугольника внутри холста? - PullRequest
11 голосов
/ 16 февраля 2011

Я не знаю, как зарегистрировать событие щелчка для каждого прямоугольника.

вот пример:

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

Ответы [ 5 ]

24 голосов
/ 17 февраля 2011

Вам нужно будет отслеживать, где находятся ваши прямоугольники на холсте, а затем настроить прослушиватель событий на самом холсте. Оттуда вы можете взять координаты события щелчка и пройти все свои прямоугольники, чтобы проверить «столкновения».

Вот пример того, как это сделать: 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);
}
13 голосов
/ 28 октября 2012

Это старый вопрос, но то, что раньше было трудно сделать, когда он был опубликован, теперь намного проще.

Существует множество библиотек, которые отслеживают положение ваших объектов, которые были нарисованы на холсте и обрабатывалисьвсе сложности обработки взаимодействия с мышью.См. EaselJS , KineticJS , Paper.js или Fabric.js и это сравнение библиотек холста для получения дополнительной информации..

Вы также можете использовать другой подход и использовать Raphaël и gRaphaël , чтобы получить решение, которое использует SVG и VML вместо canvas и работает даже в 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 , API векторного рисования с сохранением режима для холста HTML5 - см. этот ответ для получения дополнительной информации.

2 голосов
/ 24 июля 2012

Я нашел способ заставить это работать в 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/

0 голосов
/ 11 мая 2017

Пожалуйста, используйте функцию ниже, если вы хотите поддерживать более одного прямоугольника на холсте и обрабатывать его событие клика

<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/

0 голосов
/ 22 сентября 2016

Пожалуйста, используйте функцию ниже, если вы хотите поддерживать более одного прямоугольника на холсте и обрабатывать его событие щелчка ..... измененная логика, данная Мэттом Кингом.

...