Jak dodać prostą obsługę zdarzenia onClick do elementu canvas?
Jestem doświadczonym programistą Java, ale patrzę na niektóre rzeczy JavaScript / HTML5 po raz pierwszy od około dekady. Nie wiem, co powinno być najprostsze.
Jako przykład chciałem coś narysować i dodać do tego obsługę zdarzenia. Jestem pewien, że robię coś głupiego, ale szukałem wszędzie i nic, co jest sugerowane (np. odpowiedź na to pytanie: Add onclick property to input with JavaScript ) nie działa. Używam Firefoksa 10.0.1. Mój kod jest następujący. Zobaczysz kilka skomentowanych linii, a na końcu każdego z nich znajduje się opis tego, co (lub co nie) się dzieje.
Jaka jest poprawna składnia? Wariuję!
<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>
7 answers
Gdy rysujesz do elementu canvas
, po prostu rysujesz bitmapę w trybie natychmiastowym.
Elementy (kształty, linie, obrazy), które są rysowane, nie mają żadnej reprezentacji poza używanymi pikselami i ich kolorem.
Dlatego, aby uzyskać kliknij Zdarzenie na canvas
element (kształt), musisz uchwycić zdarzenia kliknięcia na elemencie HTML canvas
i użyć matematyki, aby określić, który element został kliknięty, pod warunkiem, że przechowujesz szerokość/wysokość elementów oraz przesunięcie x / y.
Aby dodać zdarzenie click
do elementu canvas
, użyj...
canvas.addEventListener('click', function() { }, false);
Aby określić, który element został kliknięty...
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 .
Ten kod dołącza Zdarzenie click
do elementu canvas
, a następnie wypycha jeden kształt (zwany element
w moim kodzie) do tablicy elements
. Możesz tu dodać tyle, ile chcesz.
Celem tworzenia tablicy obiektów jest sprawdzenie ich właściwości później. Po wypchnięciu wszystkich elementów na tablicę, wykonujemy pętlę i renderujemy każdy z nich na podstawie ich właściwości.
Po wywołaniu zdarzenia click
, kod przecina elementy i określa, czy kliknięcie nastąpiło nad którymkolwiek z elementów tablicy elements
. Jeśli tak, to uruchamia alert()
, które można łatwo zmodyfikować, aby zrobić coś takiego, jak usunięcie elementu tablicy, w którym to przypadku potrzebujesz oddzielnej funkcji render , aby zaktualizować canvas
.
Dla kompletność, dlaczego twoje próby nie zadziałały...
elem.onClick = alert("hello world"); // displays alert without clicking
Jest to przypisanie wartości zwracanej alert()
do właściwości onClick
elem
. Od razu przywołuje alert()
.
elem.onClick = alert('hello world'); // displays alert without clicking
W JavaScript, '
i "
są semantycznie identyczne, lexer prawdopodobnie używa ['"]
do cudzysłowów.
elem.onClick = "alert('hello world!')"; // does nothing, even with clicking
Przypisujesz łańcuch do onClick
właściwości elem
.
elem.onClick = function() { alert('hello world!'); }; // does nothing
JavaScript rozróżnia wielkość liter. Właściwość onclick
jest archaiczną metodą dołączania obsługa zdarzeń. Pozwala na dołączenie tylko jednego zdarzenia z właściwością i zdarzenie może zostać utracone podczas serializacji HTML.
elem.onClick = function() { alert("hello world!"); }; // does nothing
Jeszcze raz, ' === "
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-24 13:43:26
Polecam następujący artykuł: Hit Region Detection for HTML5 Canvas And How to Listen To Click Events On Canvas Shapes which goes through different situations.
Nie obejmuje jednak API addHitRegion
, które musi być najlepszym sposobem(korzystanie z funkcji matematycznych i / lub porównań jest dość podatne na błędy). To podejście jest szczegółowe na dewelopera.mozilla
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-23 10:22:36
Jako alternatywa dla odpowiedzi Alexa:
Można użyć rysunku SVG zamiast rysunku Canvas. Tam można dodawać zdarzenia bezpośrednio do rysowanych obiektów DOM.
Zobacz na przykład:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:09
Można również umieścić elementy DOM, takie jak div
Na wierzchu obszaru roboczego, które reprezentowałyby twoje elementy obszaru roboczego i były umieszczone w ten sam sposób.
Teraz możesz dołączyć słuchacze zdarzeń do tych Div I uruchomić niezbędne akcje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-31 16:22:06
Jako kolejna tania alternatywa na nieco statycznym płótnie, użycie nakładającego się elementu img z definicją usemap jest szybkie i brudne. Działa szczególnie dobrze na elementach płótna opartych na wielokątach, takich jak Wykres kołowy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-11 18:44:30
Prawdopodobnie bardzo późno na odpowiedź, ale właśnie przeczytałam to przygotowując się do egzaminu 70-480
i okazało się, że to działa -
var elem = document.getElementById('myCanvas');
elem.onclick = function() { alert("hello world"); }
Zwróć uwagę na zdarzenie jako onclick
zamiast onClick
.
Js Bin przykład.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-22 19:36:38
Alex Answer jest całkiem zgrabna, ale podczas obracania kontekstu może być trudno prześledzić współrzędne x,y, więc zrobiłem Demo pokazujące, jak to śledzić.
Zasadniczo używam tej funkcji i podaję jej kąt i ilość przebytej odległości w tym Aniele przed narysowaniem obiektu.
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
};
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:09