본문 바로가기

Visualization/D3Js

D3 :: select(), selectAll()을 이용한 문서요소 만들기

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 = [1234 ,5];
    
    var selection = d3.select("body")
        .selectAll("p")
        .data(theData)
        .enter()
        .append("p")
        .text("Hello D3.js");
 
    console.log(selection);
 
  </script>
</body>
 
</html>
cs

결과


소스코드 분석


"body" 요소 선택  ->  존재하지 않는 요소("p")에 대한 빈 참조를 반환  ->  생성할 문서요소에 데이터 바인딩  ->  placeholder에 대한 참조반환  ->  DOM에 문서요소("p") 추가  -> 문서요소("p")에 텍스트 삽입

위 소스코드의 간략한 흐름은 위와 같다. 아래부터는 라인단위로 포함된 메소드에 대한 좀더 자세한 설명이다.

var theData = [1234 ,5];

  • DOM에 바인딩 하기위한 배열데이터를 선언한다.

var selection = d3.select("body")

d3

  • d3 글로벌 객체를 통해서 d3에 있는 메소드들을 사용할 수 있다.

select()

  • 메소드에 전달인자로 css 선택자를 주면 조건과 일치하는 첫번째 DOM 문서요소의 참조를 반환한다.
  • 매치되지 않으면 빈 selection 객체를 반환한다.
  • d3.select는 선택된 문서요소("body")를 원소로 하는 한 개의 group 배열(0: Array[1])을 원소로 하는 배열(Array[1])을 반환한다.

.selectAll("p")

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()

  • 전달 인자로 문자열을 받아서 해당 선택된 문서요소의 여는 태그와 닫는 태그사이에 추가한다.
실제화된 "p" 문서요소의 참조를 전달 받았기 때문에 <p> 태그에 문자열이 위치하게 된다.


결론

각 operator들이 의미하는 바와 단계적으로 실행했을때의 객체와 배열의 변화를 직접 확인해보기 전까지 문서요소 생성시에 같은 요소를 입력받는 selectAll 과 append의 차이에 대해서 이해하기가 쉽지 않았다. 중요한 것은  존재하지 않는 DOM 요소를 생성할때에 selectAll은 해당 문서요소를 실제화 하지 못하고 selectAll() -> data() -> enter() -> append()의 과정속에서 최종적으로 append() 하였을때 문서요소가 실제화 된다는 것이다. 또한 메소드 체인을 통해 객체를 전달, 반환, 참조 전달 을 실행하는 d3의 흐름을 잘이해하기 위해 selection 객체의 변화를 잘 파악하는 것이 중요한 것 같다.


참조

http://blog.nacyot.com/articles/2015-02-02-d3-selection/ :: D3.js 기초 - select API와 enter() 이해하기