2013-05-28 3 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과 원 중심 사이의 거리가 반지름보다 작은 지 확인하십시오.

반경이 r이고 중심이 (x0,y0)이고 점이 (x1,y1) 인 원을 가정 해 봅시다. 그 점이 원 안에 있는지 확인하고 싶습니다. 자바 스크립트에서

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

:

나는로 변환하는 d((x0,y0),(x1,y1)) < r 여부를 확인해야 할 것입니다.

이제 xy되는 bubble.xbubble.y(x1,y1)되는 모든 값 (x0,y0)을 알고있다.

+0

p1은 원의 중심입니다 (이미 너비/2와 높이/2를 수행하여 계산 한 것입니다). p2는 원을 확인하는 현재 마우스 위치입니다. –

3

그냥 마우스 포인터와 원의 중심 사이의 distance를 계산 한 후 내부의 여부를 결정 :

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

if (dist < bubble.r) { 
    alert('hello'); 
} 
코멘트에 mentioned으로

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!") 
} 

경로는 btw입니다. 어떤 모양이든. 자세한 내용은

: 주어진 점과 원의 중심 사이의 거리의 반경보다작은 경우 포인트가 원 내에있는 경우
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의 반환 한 시험 : 커서와 원의 위치와 크기의 위치를 ​​알고 (그리고 정말 원,하지 생략되어 있으면)

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

+1

읽기 쉽고 재사용 가능한 코드를 만들어 주셔서 감사합니다. 현대의 브라우저에서 성능 테스트에 대한 메모를 보면 제곱근을 사용하는 것이 약간 빨라 졌다고 보입니다. – pedalpete

관련 문제