Как добавить простой обработчик события onClick к элементу canvas?

javascript html5 canvas event-handling onclick

201733 просмотра

7 ответа

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

В качестве примера я просто хотел нарисовать что-то и добавить к нему обработчик событий. Я уверен, что делаю что-то глупое, но я искал повсюду, и ничего, что предлагается (например, ответ на этот вопрос: добавить свойство onclick для ввода с помощью JavaScript ), не работает. Я использую Firefox 10.0.1. Мой код следует. Вы увидите несколько закомментированных строк и в конце каждой будет описание того, что (или что не происходит) происходит.

Какой правильный синтаксис здесь? Я схожу с ума!

<html>
<body>
    <canvas id="myCanvas" width="300" height="150"/>
    <script language="JavaScript">
        var elem = document.getElementById('myCanvas');
        // elem.onClick = alert("hello world");  - displays alert without clicking
        // elem.onClick = alert('hello world');  - displays alert without clicking
        // elem.onClick = "alert('hello world!')";  - does nothing, even with clicking
        // elem.onClick = function() { alert('hello world!'); };  - does nothing
        // elem.onClick = function() { alert("hello world!"); };  - does nothing
        var context = elem.getContext('2d');
        context.fillStyle = '#05EFFF';
        context.fillRect(0, 0, 150, 100);
    </script>

</body>

Автор: Jer Источник Размещён: 12.11.2019 09:12

Ответы (7)


198 плюса

Решение

Когда вы рисуете canvasэлемент, вы просто рисуете растровое изображение в непосредственном режиме .

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

Поэтому, чтобы получить событие щелчка по canvas элементу (фигуре), вам нужно захватить события щелчка по canvasэлементу HTML и использовать некоторую математику, чтобы определить, какой элемент был нажат, при условии, что вы сохраняете ширину / высоту элементов и смещение по оси x / y. ,

Чтобы добавить clickсобытие к вашему canvasэлементу, используйте ...

canvas.addEventListener('click', function() { }, false);

Чтобы определить, какой элемент был нажат ...

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 x = event.pageX - elemLeft,
        y = event.pageY - elemTop;

    // Collision detection between clicked offset and element.
    elements.forEach(function(element) {
        if (y > element.top && y < element.top + element.height 
            && x > element.left && x < element.left + element.width) {
            alert('clicked an element');
        }
    });

}, false);

// Add element.
elements.push({
    colour: '#05EFFF',
    width: 150,
    height: 100,
    top: 20,
    left: 15
});

// Render elements.
elements.forEach(function(element) {
    context.fillStyle = element.colour;
    context.fillRect(element.left, element.top, element.width, element.height);
});​

jsFiddle .

Этот код присоединяет clickсобытие к canvasэлементу, а затем помещает одну фигуру ( elementв моем коде это называется ) в elementsмассив. Вы можете добавить столько, сколько хотите здесь.

Цель создания массива объектов состоит в том, чтобы мы могли запросить их свойства позже. После того, как все элементы были помещены в массив, мы перебираем и отображаем каждый из них на основе их свойств.

Когда clickсобытие инициируется, код проходит по элементам и определяет, был ли клик по любому из элементов в elementsмассиве. Если это так, он запускает оператор alert(), который можно легко изменить, чтобы сделать что-то, например, удалить элемент массива, и в этом случае вам потребуется отдельная функция рендеринга для обновления canvas.

Для полноты, почему ваши попытки не сработали ...

elem.onClick = alert("hello world"); // displays alert without clicking

Это присвоение возвращаемого значения alert()к onClickсвойству elem. Это сразу вызывает alert().

elem.onClick = alert('hello world');  // displays alert without clicking

В JavaScript, то 'и "семантический идентичны, лексические , вероятно , использует ['"]для котировок.

elem.onClick = "alert('hello world!')"; // does nothing, even with clicking

Вы присваиваете строку onClickсвойству elem.

elem.onClick = function() { alert('hello world!'); }; // does nothing

JavaScript чувствителен к регистру. onclickСвойство является архаичным способом прикрепления обработчиков событий. Это позволяет только одному событию быть присоединенным со свойством, и это событие может быть потеряно при сериализации HTML.

elem.onClick = function() { alert("hello world!"); }; // does nothing

Опять же , ' === ".

Автор: alex Размещён: 26.03.2012 09:43

3 плюса

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

Тем не менее, он не охватывает addHitRegionAPI, который должен быть лучшим способом (использование математических функций и / или сравнений довольно подвержено ошибкам). Этот подход подробно описан на developer.mozilla

Автор: RUser4512 Размещён: 23.02.2018 10:22

2 плюса

Возможно, очень поздно до ответа, но я просто прочитал это, готовясь к 70-480экзамену, и обнаружил, что это работает -

var elem = document.getElementById('myCanvas');
elem.onclick = function() { alert("hello world"); }

Обратите внимание на событие как onclickвместо onClick.

Пример JS Bin .

Автор: Soham Dasgupta Размещён: 22.06.2018 07:20

1 плюс

В качестве альтернативы ответу Алекса:

Вы можете использовать рисунок SVG вместо рисунка Canvas. Там вы можете добавлять события непосредственно к нарисованным объектам DOM.

см. например:

Делаем объект изображения svg кликабельным с помощью onclick, избегая абсолютного позиционирования

Автор: Goswin Размещён: 14.10.2015 12:35

1 плюс

Вы также можете поместить элементы DOM, например, divповерх холста, которые будут представлять ваши элементы холста и располагаться таким же образом.

Теперь вы можете прикрепить прослушиватели событий к этим элементам div и выполнить необходимые действия.

Автор: Sergei Basharov Размещён: 31.03.2016 04:22

0 плюса

Alex Response довольно аккуратный, но при использовании поворота контекста может быть сложно отследить координаты x, y, поэтому я сделал демонстрацию, показывающую, как это отслеживать.

В основном я использую эту функцию и задаю ей угол и расстояние, пройденное в этом ангеле до рисования объекта.

function rotCor(angle, length){
    var cos = Math.cos(angle);
    var sin = Math.sin(angle);

    var newx = length*cos;
    var newy = length*sin;

    return {
        x : newx,
        y : newy
    };
}
Автор: Imran Bughio Размещён: 24.01.2017 03:55

0 плюса

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

Автор: TadLewis Размещён: 11.04.2018 06:44
Вопросы из категории :
32x32