Je suis un programmeur expérimenté en Java, mais je suis en train de regarder quelques éléments JavaScript/HTML5 pour la première fois depuis environ une décennie. Je suis complètement perplexe sur ce qui devrait être la chose la plus simple de tous les temps.
Par exemple, je voulais juste dessiner quelque chose et y ajouter un gestionnaire d'événements. Je suis sûr que je fais quelque chose de stupide, mais j'ai cherché partout et rien qui est suggéré (par exemple la réponse à cette question: Ajouter la propriété onclick pour entrer avec JavaScript ) fonctionne. J'utilise Firefox 10.0.1. Mon code suit. Vous verrez plusieurs lignes commentées et à la fin de chacune se trouve une description de ce qui se passe (ou de ce qui ne se passe pas).
Quelle est la syntaxe correcte ici? Je deviens fou!
<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>
Lorsque vous dessinez un élément canvas
, vous dessinez simplement une image bitmap dans mode immédiat .
Les éléments (formes, lignes, images) dessinés n'ont aucune représentation en dehors des pixels qu'ils utilisent et de leur couleur.
Par conséquent, pour obtenir un événement click sur une canvas
élément (forme), vous devez capturer des événements de clic sur l’élément HTML canvas
et utiliser des calculs mathématiques pour déterminer l’élément sur lequel vous avez cliqué, à condition que vous stockiez les éléments. éléments 'largeur/hauteur et décalage x/y.
Pour ajouter un événement click
à votre élément canvas
, utilisez ...
canvas.addEventListener('click', function() { }, false);
Pour déterminer quel élément a été cliqué ...
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 .
Ce code attache un événement click
à l'élément canvas
, puis pousse une forme (appelée element
dans mon code) dans un tableau elements
. Vous pouvez en ajouter autant que vous le souhaitez ici.
La création d’un tableau d’objets a pour but de pouvoir interroger leurs propriétés ultérieurement. Une fois que tous les éléments ont été placés sur le tableau, nous les parcourons et les rendons en fonction de leurs propriétés.
Lorsque l'événement click
est déclenché, le code parcourt les éléments et détermine si le clic a été effectué sur l'un des éléments du tableau elements
. Si tel est le cas, il déclenche une alert()
, qui pourrait facilement être modifiée pour supprimer le tableau, ce qui nécessiterait une fonction render distincte pour mettre à jour la canvas
.
Pour être complet, pourquoi vos tentatives n'ont pas fonctionné ...
elem.onClick = alert("hello world"); // displays alert without clicking
Ceci affecte la valeur de retour de alert()
à la propriété onClick
de elem
. Il appelle immédiatement la alert()
.
elem.onClick = alert('hello world'); // displays alert without clicking
En JavaScript, '
et "
sont sémantiquement identiques, le lexer utilise probablement ['"]
pour les guillemets.
elem.onClick = "alert('hello world!')"; // does nothing, even with clicking
Vous affectez une chaîne à la propriété onClick
de elem
.
elem.onClick = function() { alert('hello world!'); }; // does nothing
JavaScript est sensible à la casse. La propriété onclick
est la méthode archaïque d’attachement de gestionnaires d’événements. Il ne permet d'associer qu'un seul événement à la propriété et cet événement peut être perdu lors de la sérialisation du code HTML.
elem.onClick = function() { alert("hello world!"); }; // does nothing
Encore une fois, ' === "
.
Je recommande l'article suivant: Détection de la région ciblée pour le canevas HTML5 et comment écouter les événements de clic sur les formes du canevas qui passe par diverses situations.
Cependant, il ne couvre pas l'API addHitRegion
, qui doit être la meilleure solution (l'utilisation de fonctions mathématiques et/ou de comparaisons est assez sujette aux erreurs). Cette approche est détaillée sur developer.mozilla
Probablement très tard pour la réponse, mais je viens de lire ceci en préparant mon examen 70-480
et j'ai trouvé que cela fonctionnait
var elem = document.getElementById('myCanvas');
elem.onclick = function() { alert("hello world"); }
Notez l'événement en tant que onclick
au lieu de onClick
.
JS Bin exemple.
Vous pouvez également placer des éléments DOM, tels que div
, sur le canevas, qui représenteraient vos éléments de canevas et seraient positionnés de la même manière.
Vous pouvez maintenant attacher des écouteurs d'événements à ces divs et exécuter les actions nécessaires.
Comme alternative à la réponse d'Alex:
Vous pouvez utiliser un dessin SVG au lieu d'un dessin Canvas. Là, vous pouvez ajouter des événements directement aux objets DOM dessinés.
voir par exemple:
Rendre un objet image svg cliquable avec onclick, en évitant le positionnement absolu
En tant qu'alternative peu coûteuse sur un canevas quelque peu statique, l'utilisation d'un élément img superposé avec une définition de carte d'usin est rapide et sale. Fonctionne particulièrement bien sur les éléments de canevas basés sur des polygones, comme un graphique à secteurs.
Alex Answer est assez soigné, mais lorsque vous utilisez la rotation de contexte, il peut être difficile de tracer les coordonnées x, y. J'ai donc créé une Demo montrant comment en tenir compte.
En gros, j'utilise cette fonction et lui donne l'angle et la distance parcourue dans cet ange avant de dessiner un objet.
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
};
}