2013-05-28 10 views
30

Come posso rilevare quando l'utente fa clic all'interno della bolla rossa?Rileva se l'utente fa clic all'interno di un cerchio

Non dovrebbe essere come un campo quadrato. Il mouse deve essere veramente all'interno del cerchio:

img

Ecco il codice:

<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> 
+1

Se si conosce la posizione del cursore e la posizione e la dimensione del cerchio (ed è davvero un cerchio, non i puntini di sospensione), è solo una semplice calcolo geometrico per determinare se il punto (il cursore) si trova all'interno del cerchio o meno. http://stackoverflow.com/questions/481144/equation-for-testing-if-a-point-is-inside-a-circle – qJake

+0

Sentito parlare di seno e coseno ...? – CBroe

+1

@CBroe Trig non è necessario in questo caso, né sarebbe utile. –

risposta

45

Un cerchio, è la posizione geometrica di tutti i punti la cui distanza dal punto centrale è pari a circa numero "R".

Si desidera trovare i punti la cui distanza è inferiore o uguale a quella "R", il nostro raggio.

L'equazione di distanza nello spazio euclideo 2d è d(p1,p2) = root((p1.x-p2.x)^2 + (p1.y-p2.y)^2).

Verificare se la distanza tra lo p e il centro del cerchio è inferiore al raggio.

Diciamo che ho un cerchio con raggio r e al centro in posizione (x0,y0) e un punto (x1,y1) e voglio verificare se questo punto si trova nel cerchio o meno.

avrei bisogno di controllare se d((x0,y0),(x1,y1)) < r che si traduce in:

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

In JavaScript.

Ora sapete tutti questi valori (x0,y0) essendo bubble.x e bubble.y e (x1,y1) essere x e y.

+0

p1 è il centro del cerchio (che hai già calcolato facendo larghezza/2 e altezza/2). p2 è la posizione corrente del mouse che stai verificando rispetto al cerchio. –

3

Basta calcolare il distance tra il puntatore del mouse e il centro del cerchio, poi decidere se è dentro:

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

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

Demo

Come mentioned nei commenti, per eliminare Math.sqrt() è possibile utilizzare:

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

if (distsq < rsq) { 
    alert('HELLO'); 
} 
+5

Puoi anche ritagliare il Math.sqrt "costoso" testando in questo modo: dx * dx + dy * dy markE

+0

@markE punto eccellente :) grazie! –

2

Un'alternativa (significato non sempre utile sarà onl lavoro y per l'ultimo percorso (ri) definita, ma ne parlo come opzione):

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

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

percorso può btw. essere di qualsiasi forma

Per maggiori dettagli:
http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath

+0

+1 per una risposta che comprende qualsiasi percorso. Assicurati di menzionare che il percorso da testare deve essere definito (o ridefinito) appena prima del hit-testing con isPointInPath. – markE

26

per verificare se un punto è all'interno di un cerchio, si vuole determinare se la distanza tra il punto dato e il centro del cerchio è più piccolo del raggio il cerchio.

Invece di utilizzare la formula punto-distanza, che prevede l'uso di una radice quadrata (lenta), è possibile confrontare la distanza non quadrata (o ancora al quadrato) tra i punti.Se la distanza è inferiore al raggio al quadrato, allora sei arrivato!

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

(non utilizzando il codice perché voglio mantenere la funzione generale per gli spettatori che vengono a questa domanda in seguito)

Questo è leggermente più complicato da comprendere, ma è anche più veloce, e se avete intenzione sempre controllando point-in-circle in un ciclo di animazione di disegno/animazione/oggetto, quindi vorrai farlo nel modo più veloce possibile.

JS correlati prova perf:

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

+1

Grazie per aver reso questo codice leggibile e riutilizzabile. Solo una nota sul test delle prestazioni, nei browser moderni, sembra che l'utilizzo della radice quadrata sia sempre leggermente più veloce. – pedalpete

Problemi correlati