HTML5 캔버스에서 베지어 경로 도형의 클릭 감지 방법
HTML5 캔버스에서는 isPointInPath() 메서드 대신 픽셀 데이터 기반 충돌 검사를 사용하여 베지어(Bezier) 경로로 그려진 복잡한 도형의 클릭 여부를 정확하게 판별할 수 있습니다.
핵심 원리는 다음과 같습니다.
- 각 도형을 임시(고스트) 캔버스 컨텍스트에 하나씩 그립니다.
getImageData()를 사용해 마우스 클릭 좌표에 해당하는 픽셀 1개의 데이터를 읽어옵니다.- 픽셀의 알파 채널 값(투명도)이 0보다 크면, 해당 위치에 도형이 존재한다는 의미이므로 클릭된 것으로 판단합니다.
예제 코드
var l = boxes.length;
for (var i = l-1; i >= 0; i--) {
// 현재 도형을 고스트 컨텍스트에 그리기
drawshape(gctx, boxes[i], 'black', 'black');
// 클릭 좌표(mx, my)의 픽셀 1개 데이터 가져오기
var imgData = gctx.getImageData(mx, my, 1, 1);
var index = (mx + my * imgData.width) * 4;
// 알파 채널(data[3])이 0보다 크면 도형 위를 클릭한 것
if (imgData.data[3] > 0) {
mySel = boxes[i];
offsetx = mx - mySel.x;
offsety = my - mySel.y;
mySel.x = mx - offsetx;
mySel.y = my - offsety;
isDrag = true;
canvas.onmousemove = myMove;
invalidate();
clear(gctx);
return;
}
}
코드 동작 설명
1. 역순 순회 — boxes 배열을 뒤에서부터 탐색하므로, 나중에 그려져 화면상 가장 위에 있는 도형을 우선적으로 감지합니다.
2. 픽셀 인덱스 계산 — (mx + my * imgData.width) * 4 공식으로 클릭 지점 픽셀의 배열 내 위치를 구합니다. 각 픽셀은 R, G, B, A 순서의 4바이트로 저장되므로 4를 곱합니다.
3. 알파 값 검사 — imgData.data[3]은 알파(투명도) 채널입니다. 이 값이 0보다 크면 클릭한 지점에 도형이 그려져 있다는 뜻이며, 즉시 해당 도형을 선택 객체(mySel)로 지정하고 드래그 상태로 전환한 뒤 함수를 종료합니다.
참고 사항
도형 개수가 많으면 매번 전체를 다시 그리며 검사하는 방식은 성능 부담이 될 수 있습니다. 이 경우 오프스크린 캔버스에 도형 ID별 색상을 미리 렌더링해 두고, 클릭 시 색상만 조회하는 컬러 피킹(color picking) 기법을 함께 고려하면 효율적입니다.