d3 데이터를 dom에 바인딩하기

d3의 가장 기초가 되는 메소드에 대해 알아보자

select

조작하고자 하는 DOM 요소를 선택할 수 있다.

반환되는 값은 selection 객체이다.

해당하는 결과가 없을 경우 빈 객체를 반환한다.

부모의 데이터와 인덱스등의 상태를 보존한 상태로 선택한다.

selectAll

선택자와 함께 DOM 요소를 여러 개 선택한다.

반환되는 값은 selection 객체 배열이다.

해당하는 결과가 없을경우 빈 객체 배열을 반환한다.

부모의 데이터와 인덱스등의 상태를 보존하지 않은 상태로 새 그룹을 만든다.

즉 새로운 데이터를 바인딩하기 위해선 select가 아닌 selectAll을 사용해야한다.

datum

요소에 단일 데이터를 바인딩 할 때 사용한다.

실제 DOM요소와의 연결을 계산하지 않는다.(enter,update,exit)

단순히 모든 요소에 할당한다.

1
2
3
4
5
6
const data = 1;
d3.select("body").datam(data).enter().append("div");

const datas = [1, 2, 3];
d3.select("body").datam(datas).enter().append("div");
// 모든 요소에 1,2,3을 할당

parameter를 제공하지 않을경우, 선택된 첫번째 요소의 데이터만을 반환한다.

위의 예시에서는 1을 반환한다.

data

데이터 배열을 selection 객체와 연결한다.

실제 DOM 요소와 연결하기 위해 이를 계산한다.

때문에 data를 수행할 경우 selection 객체는 enter,exit,update의 메소드를 갖게된다.

즉 데이터 각각을 실제 DOM 요소와 연결할 수 있다.

data를 수행할 경우 index를 key로 갖게 되는데, data함수 내부의 두 번째 parameter에 key function을 제공하여 고유한 키를 갖도록 할 수 있다.

1
2
3
4
5
6
7
const data = 1;
d3.select("body").data([data]).enter().append("div");
// 배열로 제공하였다.

const datas = [1, 2, 3];
d3.select("body").data(datas).enter().append("div");
// 실제 DOM 요소와의 연결이 존재하지 않는 2,3번째 요소에 2,3을 할당하여 enter

이중 enter()는 selection 객체에 바인드된 데이터 중에 실제 DOM을 가지지 못하는 요소를 찾아내 가상의 객체로 만들어 반환한다.

즉 데이터의 수가 DOM요소보다 많을 경우 하는 작업이다.

1
2
const data = [1, 2, 3];
d3.select("body").data(data).enter().append("div");

update는 업데이트된 데이터에 따라 어떻게 작업할지를 명시한다.

data 자체가 update이다.

1
2
const data = [1, 2, 3];
d3.select("body").data(data).attr("update");

exit은 업데이트된 데이터에 따라 요소를 제거할 때에 사용된다.

즉 데이터의 수가 DOM요소보다 적을 경우 하는 작업이다.

1
2
const data = [1, 2, 3];
d3.select("body").data(data).exit().remove();

parameter를 제공하지 않을경우, 선택된 요소에 대해 바인딩 된 데이터를 배열로 반환한다.

위의 예시에서는 [1,2,3] 을 반환한다.

join

enter,exit,update를 함수 하나에 정의할 수 있다.

즉 예전 general update pattern에 대한 대안이다.

일일히 정의해줄 수도 있다.

1
2
3
4
5
6
7
8
const data = [1, 2, 3];
d3.select("body")
.data(data)
.join(
(enter) => enter.append("div"),
(update) => update.attr("class", "update"),
(exit) => exit.remove()
);

예시

1
2
3
<div>hi</div>
<div>hi</div>
<div>hi</div>
1
2
3
4
const data = [1, 2, 3];
let dom = d3.select("body").selectAll("div").data(data).enter();

dom.append("div").text("hello");

즉 위의 코드의 결과는 다음과 같다.(enter)

1
2
3
4
5
<div>hi</div>
<div>hi</div>
<div>hi</div>
<div>hello</div>
<div>hello</div>
1
2
3
<div>hi</div>
<div>hi</div>
<div>hi</div>
1
2
const data = [1, 2, 3];
d3.select("body").selectAll("div").data(data).text("hello");

다음과 같이 수정하면 hello 5개로 구성된 HTML을 얻을 수 있다.(update)

1
2
3
4
5
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>

Ref

https://github.com/d3/d3-selection#joining-data
https://bost.ocks.org/mike/join/
https://bost.ocks.org/mike/nest/
https://stackoverflow.com/questions/13728402/what-is-the-difference-d3-datum-vs-data
https://www.intothevoid.io/data-visualization/understanding-d3-data-vs-datum/

댓글