2013-05-28 7 views
30

ユーザーが赤い泡の中をクリックしたときはどうすれば検出できますか?ユーザーが円内をクリックしたかどうかを検出する

正方形のフィールドのようにはなりません。マウスは、円の内側に本当にでなければならない:

img

はここでは、コードは次のとおり

<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

です(カーソル)が円内にあるかどうかを決定するための幾何学的計算。 http://stackoverflow.com/questions/481144/equation-for-testing-if-a-point-is-inside-a-circle – qJake

+0

洞穴と余弦の聞こえます...? – CBroe

+1

@CBroe Trigはこの場合必要ではなく、有用でもありません。 –

答えて

45

円、距離、中心点からいくつかに等しい全ての点の幾何学的位置であります数字「R」。

距離がその「R」以下である点を探したいとします。

ユークリッド空間の距離式は、d(p1,p2) = root((p1.x-p2.x)^2 + (p1.y-p2.y)^2)です。

pと円の中心との距離が半径より小さいかどうかを確認してください。

のは、私が位置 (x0,y0)とポイント (x1,y1)における半径 rと中心とした円を持っていると私はその点が円の中にあるかどうかをチェックしたいとしましょう。 JavaScriptでは

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

私はに変換されd((x0,y0),(x1,y1)) < rかどうかを確認する必要があると思います。

今、あなたはすべてのこれらの値(x0,y0)bubble.xbubble.y(x1,y1)xyことを知っています。

+0

p1はサークルの中心です(既に幅/ 2と高さ/ 2を計算して計算しています)。 p2は、あなたが円に対してチェックしている現在のマウスの位置です。 –

3

ただ、それは内部のかどうかを決定し、その後、マウスポインタやサークルの中心とdistanceを計算する:mentionedとして

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

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

Demo

コメントで、あなたが使用することができますMath.sqrt()排除するために:

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

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

「高価な」Math.sqrtを次のようにテストすることによっても除外することができます:dx * dx + dy * dy markE

+0

@markE優れた点:)ありがとう! –

2

代替手段(必ずしも有用な意味ではない)最後のパスのためのyの作業(再)定義されていますが、私はオプションとして、それを持ち出す):

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

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

パスすることができところで。どんな形でもよい。詳細について


http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath
+0

+1はすべてのパスを含む答えです。 isPointInPathでヒットテストする直前に、テストするパスを定義(または再定義)する必要があることに注意してください。 – markE

26

点が円内にあるかどうかをテストするには、所与の点と円の中心との間の距離が半径より小さいかどうかを決定します円。

(遅い)平方根を使用する点距離式を使用する代わりに、ポイント間の平方根のない(またはまだ平方の)距離を比較できます。その距離がの半径の二乗より小さい場合は、あなたは入ります!

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

これはやや複雑理解することですが、そのも速く、そしてあなたは予定がある場合(私は後でこの質問に来る見物人のための機能の一般的なを維持したいので、あなたのコードを使用していません)描画/アニメーション/オブジェクト移動ループ内のポイントインサークルを常にチェックすると、可能な限り最速の方法で実行したいと考えています。

関連JSのPERFテスト:あなたは、カーソルの位置と位置と円の大きさを(そしてそれは本当に、円ではなく、省略記号です)知っていれば、それだけで簡単な

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

+1

読みやすく再利用可能なコードを作成していただきありがとうございます。現代のブラウザでは、パフォーマンステストに関するメモだけでは、平方根を使用しているほうが少し速いと思われます。 – pedalpete

関連する問題