Wykrywa, czy użytkownik kliknie wewnątrz okręgu

Jak mogę wykryć, gdy użytkownik kliknie w czerwoną bańkę?

Nie powinno być jak kwadratowe pole. Mysz musi być naprawdę wewnątrz okręgu:

img

Oto kod:

<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>
Author: gre_gor, 2013-05-28

4 answers

Okrąg, to geometryczne położenie wszystkich punktów, których odległość od punktu centralnego jest równa pewnej liczbie "R".

Chcesz znaleźć punkty, których odległość jest mniejsza lub równa "r", nasz promień.

Równanie odległości w 2d przestrzeni euklidesowej wynosi d(p1,p2) = root((p1.x-p2.x)^2 + (p1.y-p2.y)^2).

Sprawdź, czy odległość między twoim p a środkiem okręgu jest mniejsza niż promień.

Powiedzmy, że mam okrąg o promieniu r i środku w pozycji (x0,y0) i punkt (x1,y1) i chcę sprawdzić, czy ten punkt jest w okręgu, czy nie.

Muszę sprawdzić czy {[6] } co tłumaczy się na:

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

W JavaScript.

Teraz znasz wszystkie te wartości (x0,y0) jako bubble.x i bubble.y i (x1,y1) jako x i y.

 49
Author: Benjamin Gruenbaum,
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
2013-05-28 13:06:58

Aby sprawdzić, czy punkt znajduje się w okręgu, chcesz określić, czy odległość między danym punktem a środkiem okręgu jest mniejsza niż promień okręgu.

Zamiast używać formuły punkt-odległość, która obejmuje użycie (powolnego) pierwiastka kwadratowego, można porównać odległość nie-kwadratową (lub nadal-kwadratową) między punktami. Jeśli ta odległość jest mniejsza niż promień do kwadratu , to jesteś w środku!

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

(nie używając Twojego kodu ponieważ chcę zachować funkcję ogólną dla gapiów, którzy przychodzą do tego pytania później)

Jest to nieco bardziej skomplikowane do zrozumienia, ale jest również szybsze, a jeśli zamierzasz kiedykolwiek sprawdzać punkt w okręgu w pętli ruchu rysunku / animacji / obiektu, to będziesz chciał zrobić to najszybciej jak to możliwe.

Powiązany test js perf:

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

 32
Author: Simon Sarris,
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
2013-05-29 16:15:50

Po prostu Oblicz odległość między wskaźnikiem myszy a środkiem okręgu, a następnie zdecyduj, czy znajduje się on w środku:

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

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

Demo

Jak wspomniano w komentarzach, aby wyeliminować Math.sqrt() możesz użyć:

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

if (distsq < rsq) {
   alert('HELLO');
}
 4
Author: Ja͢ck,
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:25:25

Alternatywa (nie zawsze przydatna, co oznacza, że będzie działać tylko dla ostatniej ścieżki (re)zdefiniowanej, ale podaję ją jako opcję):

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

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

Ścieżka może btw. bądź dowolny.

Po Więcej Szczegółów:
http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath

 3
Author: ,
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
2013-05-28 16:33:18