web-dev-qa-db-ja.com

ユーザーが円の内側をクリックしたかどうかを検出する

ユーザーが赤いバブル内をクリックしたことを検出するにはどうすればよいですか?

正方形のフィールドのようなものであってはなりません。マウスは本当に円の中になければなりません:

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>
34
super

円は、中心点からの距離が「R」に等しいすべての点の幾何学的位置です。

距離がその「R」以下の半径であるポイントを見つけたいと思います。

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

pと円の中心の間の距離が半径よりも小さいかどうかを確認します。

半径がrで中心が_(x0,y0)_の位置にあり、点が_(x1,y1)_である円があり、その点が円の中にあるかどうかを確認したいとします。

に変換されるd((x0,y0),(x1,y1)) < rかどうかを確認する必要があります:

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

JavaScriptで。

これで、これらすべての値_(x0,y0)_が_bubble.x_および_bubble.y_および_(x1,y1)_がxおよびyであることがわかりました。

53

ポイントが円内にあるかどうかをテストするには、指定されたポイントと円の中心の間の距離が半径よりもsmallerかどうかを判断します円の。

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

// 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パフォーマンステスト:

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

33
Simon Sarris

マウスポインタと円の中心の間の 距離 を計算し、それが内部にあるかどうかを判断します。

_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
Ja͢ck

別の方法(常に有用というわけではありませんが、最後に定義されたパスに対してのみ機能することを意味しますが、オプションとして提示します):

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

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

パスはbtwできます。どんな形でも。

詳細については:
http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath

3
user1693593