D3는 'Data-Driven Document' 라는 이름에서도 알 수 있듯이 다양한 방법으로 쉽게 Data를 DOM element에 쉽게 바인딩 할 수 있기 때문이다.
Data를 바인딩하여 출력물을 내는 간단한 예제를 통해서 D3의 기본적인 구조, selection 객체, select & selectAll 메소드 등을 알아본다.
현재 D3 v4가 release되었지만 v3, v4의 비교를 통한 공부를 하기위해 v3으로 진행한다.
기본개념에 대한 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <!DOCTYPE html> <html> <head> <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> </head> <body> <script> var theData = [1, 2, 3, 4 ,5]; var selection = d3.select("body") .selectAll("p") .data(theData) .enter() .append("p") .text("Hello D3.js"); console.log(selection); </script> </body> </html> | cs |
결과
소스코드 분석
var theData = [1, 2, 3, 4 ,5];
DOM에 바인딩 하기위한 배열데이터를 선언한다.
var selection = d3.select("body")
d3
- d3 글로벌 객체를 통해서 d3에 있는 메소드들을 사용할 수 있다.
select()
- 메소드에 전달인자로 css 선택자를 주면 조건과 일치하는 첫번째 DOM 문서요소의 참조를 반환한다.
- 매치되지 않으면 빈 selection 객체를 반환한다.
- d3.select는 선택된 문서요소("body")를 원소로 하는 한 개의 group 배열(0: Array[1])을 원소로 하는 배열(Array[1])을 반환한다.
selectAll()
- 조건과 일치하는 여러 요소를 선택하고 참조를 반환한다.
- 매치되지 않으면 빈 selection 객체를 반환한다.
- 여러개의 문서요소("p")를 원소로하는 한 개의 group 배열(0: Array[0])을 원소로 하는 배열(Array[1])을 반환한다.
선택된 "p"는 현재 존재하지 않기 때문에 group 배열 내부는 비어있다.
.data(theData)
data()
- DOM 요소에 데이터를 바인딩(첨부, 매핑)한다.
- selection.data를 통해 최말단 문서요소("p")를 원소로 하는 group 배열에 조인한다. (selection.datum은 개별 최말단 문서요소에 직접 할당)
- 데이터를 바인딩하기 위해서는 데이터와 DOM 문서요서 선택문의 두가지가 필수적으로 요구된다.
- 빈 문서요소에 데이터를 연결 짓는다.
- data() 반환 값에 대해 enter(), exit() 메소드 사용가능.
data() 까지 진행했을 때 실직적으로 아직 template상의 변화는 없다. group 배열의 length가 증가한 것은 확인가능.
.enter()
enter()
- selection에 바인드된 데이터들 중에 아직 실제 문서요소를 갖지 못 하는 것들을 찾아서 가상의 객체로 만들어 반환한다.
- 신규 문서요소의 placeholder에 대한 참조를 반환한다. placeholder는 __data__ 속성만을 가지는 단순 객체이다.
append()를 하지 않아 실제 "p" 문서요소가 포함되지는 않았지만 __data__를 갖는 가상의 object 객체(placeholder)를 원소로하는 group 배열이 생성된 것을 확인 할 수 있다.
.append("p")
append()
- 전달인자로 받은 DOM 문서요소를 새로 생성하여, 앞 체인에서 선택한 문서요소가 무엇이든 그 끝(내부)에 생성된 것을 추가한다.
- 위와 같이 비어있는 d3 selection 객체를 선택하여 진행할 시에 selectAll() -> data() -> enter() -> append() 의 과정을 통하여 문서요소를 생성한다.
이전단계에서는 문서요소가 생성되지 않았지만 append()를 통하여 template 변화와 group 배열에 가상 객체가 아닌 실제의 객체가 생성된 것을 확인할 수 있다.
.text("Hello D3.js");
text()
- 전달 인자로 문자열을 받아서 해당 선택된 문서요소의 여는 태그와 닫는 태그사이에 추가한다.
결론
각 operator들이 의미하는 바와 단계적으로 실행했을때의 객체와 배열의 변화를 직접 확인해보기 전까지 문서요소 생성시에 같은 요소를 입력받는 selectAll 과 append의 차이에 대해서 이해하기가 쉽지 않았다. 중요한 것은 존재하지 않는 DOM 요소를 생성할때에 selectAll은 해당 문서요소를 실제화 하지 못하고 selectAll() -> data() -> enter() -> append()의 과정속에서 최종적으로 append() 하였을때 문서요소가 실제화 된다는 것이다. 또한 메소드 체인을 통해 객체를 전달, 반환, 참조 전달 을 실행하는 d3의 흐름을 잘이해하기 위해 selection 객체의 변화를 잘 파악하는 것이 중요한 것 같다.