D3.js zoom 사용법
D3의 마우스/터치 이벤트에 대응하는 zoom의 사용법을 소개한다.
예제 프로그램
그래프에서 드래그(Drag)/스와이프(Swipe), 마우스 휠(Mouse wheel)/핀치 인(Pinch in)해 본다. 아래의 재설정 버튼을 클릭하면 초기 위치로 돌아간다.
예제 코드
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 v5 zoom</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script>
var width = 800;
var height = 600; // 그래프 높이
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);
var dataset = [];
for (var i = 0; i < 300; i++) {
var r = 0.5 * d3.min([height, width]) * Math.random();
var t = 2 * Math.PI * Math.random();
dataset.push({
"x": width / 2 + r * Math.cos(t),
"y": height / 2 + r * Math.sin(t)
});
}
// 축 설정
var x = d3.scaleLinear().domain([0, width]).range([0, width]);
var y = d3.scaleLinear().domain([0, height]).range([0, height]);
var xAxis = d3.axisBottom(x)
.ticks(width / height * 10) //
.tickSize(height)
.tickPadding(8 - height);
var yAxis = d3.axisRight(y)
.ticks(10)
.tickSize(width)
.tickPadding(8 - width);
var gX = svg.append("g").call(xAxis);
var gY = svg.append("g").call(yAxis);
var view = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("class", "view")
.attr("cx", function (d) { return d.x })
.attr("cy", function (d) { return d.y })
.attr("r", 5)
.attr("fill", "steelblue")
.attr("stroke", "black");
d3.select("#resetButton")
.on("click", resetted);
var zoom = d3.zoom()
.scaleExtent([1, 40])
.translateExtent([
[-100, -100],
[width + 90, height + 100]
])
.on("zoom", zoomed);
svg.call(zoom);
function zoomed(event) {
view.attr("transform", event.transform);
gX.call(xAxis.scale(event.transform.rescaleX(x)));
gY.call(yAxis.scale(event.transform.rescaleY(y)));
}
function resetted() {
svg.transition()
.duration(750)
.call(zoom.transform, d3.zoomIdentity);
}
</script>
<div>
<button id='resetButton'>reset</button>
</div>
</body>
</html>
코드 설명
zoom 설정시에는 우선, d3.zoom()
으로 zoom 이벤트의 프로토 타입을 호출하여 call
메소드로 zoom 이벤트를 등록하는 svg 요소를 설정한다. 여기서는 svg 요소를 설정하고 있지만 d3.select
, d3.selectAll
에서 선택한 요소에 등록할 수 있다.
var zoom = d3.zoom()
.scaleExtent([1, 40])
.translateExtent([
[-100, -100],
[width + 90, height + 100]
])
.on("zoom", zoomed);
svg.call(zoom);
d3.zoom()
에는 다음과 같은 함수가 제공된다.
함수 | 설명 |
---|---|
zoom.scaleExtent() |
배율의 최소 최대값을 설정한다.[k0, k1] 과 같은 두 변수의 배열로 설정한다.기본값은 [0, ∞]이다. |
zoom.translateExtent() |
이동 가능 범위를 설정한다.[[x0, y0], [x1, y1]] 과 같은 2차원 배열로 설정한다.x0, y0은 왼쪽 상단의 좌표를, x1, x2는 오른쪽 하단의 좌표를 설정한다. 기본값은 [[-∞, -∞], [+∞, +∞]] 이다. |
zoom.on(typenames, listener) |
이벤트를 등록한다. typenames 에는 다음의 3종류를 설정할 수 있다.
listener 를 null 로 하면 등록하고 있던 이벤트가 해제된다. |
on
함수는 이벤트 리스너(이벤트 시에 호출되거나 함수)를 등록한다.
function zoomed() {
view.attr("transform", d3.event.transform);
gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
gY.call(yAxis.scale(d3.event.transform.rescaleY(y)));
}
zoom의 이벤트 리스너가 호출되면 d3.event
는 현재 zoom 이벤트로 설정되고, 다음 필드가 설정된다.
메소드 | 설명 |
---|---|
d3.event.target |
관련 D3의 zoom behavior가 설정된다. |
d3.event.type |
start , zoom , end 중 하나가 설정된다. |
d3.event.transform |
현재 줌 배율, 이동량이 설정된다. |
d3.event.sourceEvent |
mousemove 및 touchmove와 같은 원래 입력 이벤트가 설정된다. |
이벤트 리스너는 d3.event.transform
을 사용하여 설정한다. d3.event.transform
을 attr
함수를 사용하여 SVG 요소의 “transform” 속성에 할당하면 현재 배율로 변환된다. 스케일에는 transform
로 설정되어 있는 다음의 함수를 사용해 변경할 수가 있다.
메소드 | 설명 |
---|---|
transform.rescaleX(scale) |
입력한 scale 의 domain 범위를 현재의 zoom값(x방향)에 맞추어 변경한다. |
transform.rescaleY(scale) |
입력한 scale 의 domain 범위를 현재 zoom 값(y 방향)에 맞게 변경한다. |
마지막으로 리셋 버튼을 누를 때 원래 위치와 배율로 되돌리는 함수를 설정한다. d3.zoomIdentity
에는 배율 0, 이동량 0의 transform 속성이 등록되어 있으며,
svg.call(zoom.transform, d3.zoomIdentity);
와 같이 call
메소드를 사용하여 호출하고 현재의 tranform 값으로 설정하면 초기 상태로 되돌릴 수 있다.
요약
마우스 조작뿐만 아니라 터치 이벤트, 핀치 인, 핀치 아웃에도 지원하고 있다.
최종 수정 : 2024-04-23