web-dev-qa-db-fra.com

Détecter si l'utilisateur clique à l'intérieur d'un cercle

Comment puis-je détecter lorsque l'utilisateur clique à l'intérieur de la bulle rouge?

Il ne doit pas ressembler à un champ carré. La souris doit être vraiment à l'intérieur du cercle:

img

Voici le code:

<canvas id="canvas" width="1000" height="500"></canvas>
<script>
var canvas = document.getElementById("canvas")
var ctx = canvas.getContext("2d")

var w = canvas.width
var h = canvas.height

var bubble = {
  x: w / 2,
  y: h / 2,
  r: 30,
}

window.onmousedown = function(e) {
    x = e.pageX - canvas.getBoundingClientRect().left
    y = e.pageY - canvas.getBoundingClientRect().top

    if (MOUSE IS INSIDE BUBBLE) {
        alert("HELLO!")
    }
}

ctx.beginPath()
ctx.fillStyle = "red"
ctx.arc(bubble.x, bubble.y, bubble.r, 0, Math.PI*2, false)
ctx.fill()
ctx.closePath()
</script>
34
super

Un cercle, est la position géométrique de tous les points dont la distance d'un point central est égale à un certain nombre "R".

Vous voulez trouver les points dont la distance est inférieure ou égale à ce "R", notre rayon.

L'équation de distance dans l'espace euclidien 2D est d(p1,p2) = root((p1.x-p2.x)^2 + (p1.y-p2.y)^2).

Vérifiez si la distance entre votre p et le centre du cercle est inférieure au rayon.

Disons que j'ai un cercle avec un rayon r et un centre à la position (x0,y0) Et un point (x1,y1) Et je veux vérifier si ce point est dans le cercle ou non.

J'aurais besoin de vérifier si d((x0,y0),(x1,y1)) < r qui se traduit par:

Math.sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)) < r

En JavaScript.

Vous connaissez maintenant toutes ces valeurs (x0,y0) Étant bubble.x Et bubble.y Et (x1,y1) Étant x et y.

53

Pour tester si un point se trouve dans un cercle, vous voulez déterminer si la distance entre le point donné et le centre du cercle est plus petite que le rayon du cercle.

Au lieu d'utiliser la formule point-distance, qui implique l'utilisation d'une racine carrée (lente), vous pouvez comparer la distance non carrée (ou toujours au carré) entre les points. Si cette distance est inférieure au rayon au carré , alors vous êtes dedans!

// x,y is the point to test
// cx, cy is circle center, and radius is circle radius
function pointInCircle(x, y, cx, cy, radius) {
  var distancesquared = (x - cx) * (x - cx) + (y - cy) * (y - cy);
  return distancesquared <= radius * radius;
}

(Ne pas utiliser votre code parce que je veux garder la fonction générale pour les spectateurs qui reviendront à cette question plus tard)

C'est un peu plus compliqué à comprendre, mais c'est aussi plus rapide, et si vous avez l'intention de vérifier un point en cercle dans une boucle de dessin/animation/objet, alors vous voudrez le faire de la manière la plus rapide possible.

Test de perf JS associé:

http://jsperf.com/no-square-root

33
Simon Sarris

Calculez simplement la distance entre le pointeur de la souris et le centre de votre cercle, puis décidez s'il est à l'intérieur:

var dx = x - bubble.x,
dy = y - bubble.y,
dist = Math.sqrt(dx * dx + dy * dy);

if (dist < bubble.r) {
  alert('hello');
}

Démo

Comme mentionné dans les commentaires, pour éliminer Math.sqrt() vous pouvez utiliser:

var distsq = dx * dx + dy * dy,
rsq = bubble.r * bubble.r;

if (distsq < rsq) {
   alert('HELLO');
}
5
Ja͢ck

Une alternative (pas toujours utile signifiant qu'elle ne fonctionnera que pour le dernier chemin (re) défini, mais je la propose en option):

x = e.pageX - canvas.getBoundingClientRect().left
y = e.pageY - canvas.getBoundingClientRect().top

if (ctx.isPointInPath(x, y)) {
    alert("HELLO!")
}

Le chemin peut btw. avoir n'importe quelle forme.

Pour plus de détails:
http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath

3
user1693593