HTML5 캔버스(Canvas)는 도형, 텍스트, 곡선 등 다양한 그래픽 요소를 자유롭게 그릴 수 있는 강력한 도구입니다. 하지만 캔버스 자체는 onClick이나 드래그 앤 드롭 같은 전통적인 DOM 이벤트를 개별 요소 단위로 지원하지 않는다는 한계가 있습니다. 캔버스 위에 그려진 모든 내용은 결국 하나의 픽셀 이미지일 뿐이기 때문입니다.
이 문제를 해결하는 대표적인 방법 중 하나가 바로 Raphael(라파엘) 프레임워크를 활용하는 것입니다. Raphael은 SVG를 기반으로 동작하며, 구버전 인터넷 익스플로러(IE)에서는 XML 기반 기술로 대체하여 호환성을 확보합니다. 덕분에 캔버스처럼 그래픽을 그리면서도 각 요소에 클릭, 드래그, 터치 이벤트를 자연스럽게 연결할 수 있습니다.
Raphael 드래그 앤 드롭 예제
아래 예제는 화면에 원 4개를 그린 뒤, 마우스나 터치로 자유롭게 끌어다 놓을 수 있도록 구현한 코드입니다.
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "utf-8">
<title>Raphaël · Drag-n-drop</title>
<link rel = "stylesheet" href = "demo.css" type = "text/css" media = "screen">
<meta name = "apple-mobile-web-app-capable" content = "yes">
<link rel = "apple-touch-icon-precomposed" href = "/Raphael.png">
<link rel = "stylesheet" href = "demo-print.css" type = "text/css" media = "print">
<script src = "raphael.js"></script>
<script>
window.onload = function () {
var R = Raphael(0, 0, "100%", "100%"),
r = R.circle(100, 100, 50).attr({fill: "hsb(0, 1, 1)", stroke: "none", opacity: .5}),
g = R.circle(210, 100, 50).attr({fill: "hsb(.3, 1, 1)", stroke: "none", opacity: .5}),
b = R.circle(320, 100, 50).attr({fill: "hsb(.6, 1, 1)", stroke: "none", opacity: .5}),
p = R.circle(430, 100, 50).attr({fill: "hsb(.8, 1, 1)", stroke: "none", opacity: .5});
var start = function () {
this.ox = this.attr("cx");
this.oy = this.attr("cy");
this.animate({r: 70, opacity: .25}, 500, ">");
},
move = function (dx, dy) {
this.attr({cx: this.ox + dx, cy: this.oy + dy});
},
up = function () {
this.animate({r: 50, opacity: .5}, 500, ">");
};
R.set(r, g, b, p).drag(move, start, up);
};
</script>
</head>
<body>
<div id = "holder"></div>
<p id = "copy">Demo of <a href = "https://raphaeljs.com/">Raphaël</a>— JavaScript Vector Library</p>
</body>
</html>
코드 핵심 로직 살펴보기
- 원 생성 —
R.circle(x, y, r)로 좌표와 반지름을 지정해 원을 만들고, HSB 색상과 투명도(opacity)를 적용합니다. - start 함수 — 드래그가 시작되면 원의 현재 위치(
cx,cy)를 저장하고, 크기가 커지면서 투명해지는 애니메이션을 실행합니다. - move 함수 — 드래그 중 발생한 이동 거리(
dx,dy)만큼 원의 위치를 실시간으로 갱신합니다. - up 함수 — 드래그가 종료되면 원을 원래 크기와 투명도로 되돌리는 애니메이션을 재생합니다.
- drag() 메서드 —
R.set(r, g, b, p).drag(move, start, up)처럼 여러 요소를 하나의 세트로 묶어 드래그 이벤트를 한 번에 등록할 수 있습니다.
이처럼 Raphael을 활용하면 복잡한 좌표 계산이나 저수준 이벤트 처리 로직을 직접 작성하지 않고도, 캔버스 스타일의 그래픽에 완전한 DOM 이벤트 기능을 손쉽게 추가할 수 있습니다. 특히 모바일 환경의 터치 이벤트까지 함께 처리해 주므로, 인터랙티브한 웹 그래픽을 개발할 때 매우 유용한 선택지입니다.