7.7 KiB
SVG와 JavaScript 이벤트 및 인터랙티브 그래프 제작
SVG는 JavaScript와 결합하여 클릭, 마우스 이동 등 다양한 이벤트를 처리할 수 있어 인터랙티브한 그래픽을 구현하는 데 이상적입니다. 여기에 getBoundingClientRect()를 활용한 좌표 변환, 그래프/차트 제작 기법, 그리고 드래그&드롭 기능을 위한 포인터 이벤트까지 설명하겠습니다.
SVG와 JavaScript 이벤트
SVG 요소는 HTML 요소처럼 DOM 이벤트(click, mouseover, mousemove 등)를 지원합니다. 이를 통해 사용자 상호작용을 감지하고 동적으로 반응할 수 있습니다.
주요 이벤트
| 이벤트 | 설명 | 사용 예시 |
|---|---|---|
click |
요소를 클릭할 때 발생. | 버튼, 토글 기능 |
mouseover |
마우스가 요소 위로 올라갈 때 발생. | 호버 효과, 툴팁 표시 |
mouseout |
마우스가 요소를 벗어날 때 발생. | 호버 효과 해제 |
mousemove |
마우스가 요소 위에서 움직일 때 발생. | 드래그, 실시간 좌표 추적 |
mousedown |
마우스 버튼을 누를 때 발생. | 드래그 시작 |
mouseup |
마우스 버튼을 뗄 때 발생. | 드래그 종료 |
예시: 클릭과 호버 이벤트
<svg width="200" height="200">
<circle id="myCircle" cx="100" cy="100" r="30" fill="blue" />
</svg>
<script>
const circle = document.getElementById("myCircle");
circle.addEventListener("click", () => circle.setAttribute("fill", "red"));
circle.addEventListener("mouseover", () => circle.setAttribute("r", "40"));
circle.addEventListener("mouseout", () => circle.setAttribute("r", "30"));
</script>
- 클릭 시 색상이 빨강으로, 호버 시 반지름이 커짐.
getBoundingClientRect()를 활용한 마우스 좌표 변환
SVG는 자체 좌표계를 사용하므로, 브라우저의 클라이언트 좌표(clientX, clientY)를 SVG 좌표로 변환해야 합니다. getBoundingClientRect()와 getScreenCTM()를 활용하면 이를 쉽게 처리할 수 있습니다.
변환 과정
getBoundingClientRect(): SVG 요소의 뷰포트 내 경계 상자 좌표를 반환.getScreenCTM(): SVG 좌표계와 화면 좌표계 간 변환 행렬을 반환.point객체: SVG 좌표로 변환된 값을 계산.
예시: 마우스 위치에 원 추가
<svg id="svgCanvas" width="400" height="400">
</svg>
<script>
const svg = document.getElementById("svgCanvas");
svg.addEventListener("click", (e) => {
const rect = svg.getBoundingClientRect();
const matrix = svg.getScreenCTM().inverse();
const point = svg.createSVGPoint();
point.x = e.clientX - rect.left;
point.y = e.clientY - rect.top;
const svgPoint = point.matrixTransform(matrix);
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circle.setAttribute("cx", svgPoint.x);
circle.setAttribute("cy", svgPoint.y);
circle.setAttribute("r", "10");
circle.setAttribute("fill", "green");
svg.appendChild(circle);
});
</script>
- 클릭한 위치에 녹색 원을 추가.
viewBox가 설정된 경우에도 정확한 SVG 좌표로 변환됨.
SVG를 활용한 인터랙티브 그래프 및 차트 제작
SVG는 데이터 시각화(막대그래프, 선그래프 등)에 적합하며, 이벤트와 동적 업데이트를 통해 인터랙티브하게 만들 수 있습니다.
예시: 인터랙티브 막대그래프
<svg id="chart" width="400" height="200" viewBox="0 0 400 200">
<g id="bars"></g>
</svg>
<script>
const data = [50, 100, 80, 120];
const svg = document.getElementById("chart");
const barsGroup = document.getElementById("bars");
data.forEach((value, index) => {
const bar = document.createElementNS("http://www.w3.org/2000/svg", "rect");
bar.setAttribute("x", index * 100);
bar.setAttribute("y", 200 - value);
bar.setAttribute("width", "80");
bar.setAttribute("height", value);
bar.setAttribute("fill", "steelblue");
bar.addEventListener("mouseover", () => bar.setAttribute("fill", "orange"));
bar.addEventListener("mouseout", () => bar.setAttribute("fill", "steelblue"));
bar.addEventListener("click", () => alert(`Value: ${value}`));
barsGroup.appendChild(bar);
});
</script>
- 막대그래프에서 호버 시 색상 변경, 클릭 시 값 표시.
기법
- 데이터 바인딩: 배열 데이터를 SVG 요소로 변환.
- 축 추가:
<line>과<text>로 x/y축 렌더링. - 툴팁:
mouseover로 동적<text>요소 표시. - 업데이트: 데이터 변경 시
removeChild와appendChild로 DOM 갱신.
드래그&드롭 (Pointer Events)
SVG에서 드래그&드롭은 pointerdown, pointermove, pointerup 이벤트를 사용해 구현합니다. 이들은 mousedown 등보다 멀티터치와 스타일러스 입력을 지원해 더 현대적입니다.
예시: 드래그 가능한 원
<svg id="svgCanvas" width="400" height="400">
<circle id="dragCircle" cx="100" cy="100" r="30" fill="purple" />
</svg>
<script>
const svg = document.getElementById("svgCanvas");
const circle = document.getElementById("dragCircle");
let isDragging = false;
circle.addEventListener("pointerdown", (e) => {
isDragging = true;
circle.setPointerCapture(e.pointerId); // 포인터 캡처 설정
});
svg.addEventListener("pointermove", (e) => {
if (!isDragging) return;
const rect = svg.getBoundingClientRect();
const matrix = svg.getScreenCTM().inverse();
const point = svg.createSVGPoint();
point.x = e.clientX - rect.left;
point.y = e.clientY - rect.top;
const svgPoint = point.matrixTransform(matrix);
circle.setAttribute("cx", svgPoint.x);
circle.setAttribute("cy", svgPoint.y);
});
svg.addEventListener("pointerup", (e) => {
isDragging = false;
circle.releasePointerCapture(e.pointerId); // 포인터 캡처 해제
});
</script>
- 원을 클릭해 드래그하면 마우스 위치로 이동.
Pointer Events 주요 속성
pointerdown: 드래그 시작.pointermove: 드래그 중 위치 업데이트.pointerup: 드래그 종료.setPointerCapture: 해당 요소가 포인터 이벤트를 독점.releasePointerCapture: 캡처 해제.
추가 팁
- 제약 조건:
Math.min/Math.max로 이동 범위 제한. - 스냅 효과: 좌표를 일정 단위로 반올림.
결론
SVG와 JavaScript 이벤트는 클릭, 호버, 드래그 등 다양한 상호작용을 가능하게 하며, getBoundingClientRect()와 좌표 변환으로 정확한 위치 계산을 지원합니다. 이를 활용해 막대그래프 같은 데이터 시각화를 만들고, 포인터 이벤트를 통해 드래그&드롭 기능을 추가할 수 있습니다. 실무에서는 D3.js 같은 라이브러리로 복잡한 차트를 쉽게 구현하거나, 순수 JavaScript로 가볍고 커스터마이징된 인터랙션을 만들 수 있습니다. SVG의 유연성과 이벤트 처리 능력은 웹에서 동적이고 사용자 친화적인 경험을 제공하는 데 큰 강점입니다.