[D3] Joining data 데이터 조인 사용법

selection.data(data, key)

지정된 데이터 배열을 선택한 요소와 바인딩합니다. 요소가 4개이고 데이터 배열이 4개의 값을 가지고 있다면 각 요소는 배열의 각 값과 바인딩됩니다. 데이터 배열의 길이가 요소의 개수와 다를 경우 enter와 exit를 선택하여 부족한 요소를 생성하거나 초과된 요소를 제거할 수 있습니다. 매개변수를 사용해서 현재 데이터, 현재 인덱스, 데이터 그룹을 가집니다. 위 매개변수로 특정 요소에 연결할 수 있습니다.

const data = [
  {name: "Locke", number: 4},
  {name: "Reyes", number: 8},
  {name: "Ford", number: 15},
  {name: "Jarrah", number: 16},
  {name: "Shephard", number: 23},
  {name: "Kwon", number: 42}
];

d3.selectAll("div")
  .data(data, function(d) { return d ? d.name : this.id; })
  .text(d => d.number);

위 코드에서 현재데이터를 d를 이용하여 data가 있으면 안에 있는 name을 선택하고 아니면 선택된 요소의 id를 선택합니다.

selection.join(enter,update,exit)

데이터를 요소에 바인딩하고, 데이터에 맞춰 요소를 추가, 업데이트 및 제거하는 편리한 방법을 제공합니다. 

svg.selectAll("circle")
  .data(data)
  .join("circle")
    .attr("fill", "none")
    .attr("stroke", "black");

위 코드에서 data 길이에 따라 circle의 선택 요소집합을 업데이트하면서 추가합니다.

svg.selectAll("circle")
  .data(data)
  .join(
    enter => enter.append("circle"),
    update => update,
    exit => exit.remove()
  )
    .attr("fill", "none")
    .attr("stroke", "black");

같은 코드를 길게 풀어쓴 코드입니다. enter는 데이터가 추가되어 새로운 요소가 필요할 때 실행, update는 기존 선택된 요소 업데이트될 때 실행, exit는 데이터가 제거되어 요소가 필요 없을 때 실행도비니다.

이제는 각각 별도의 처리를 해보겠습니다.

d3.select('svg')
    .selectAll('circle')
    .data(data)
    .join(
        enter => enter.append("circle").attr('fill','blue').attr('r',5).attr('cx',10).attr('cy',20),
        update => update.attr('fill','red'),
        exit => exit.remove()
    )

svg 태그안에 circle 요소안에 있는 circle 요소들은 red로 채우고 data 길이가 더 길면 enter로 요소들이 채워지는데 동일 장소에 파란색으로 circle를 삽입하였습니다. 이 밖에도 transition()을 활용하여 애니메이션을 적용할 수 있습니다.

이 방식으로 데이터 변경에 따른 DOM 요소의 변경을 효율적으로 처리할 수 있습니다.

selection.enter()

selection.data를 사용하여 바인딩했을 때 DOM 요소와 매칭되지 않는 새로운 데이터 항목을 위한 노드를 반환합니다. 해당 노드는 요소를 생성하는 데 사용됩니다.

즉 데이터 바인딩 후 기존 요소와 매칭되지 않는 데이터 항목에 대해 새로운 요소를 추가할 때 효율적입니다.

selection.exit()

selection.data를 사용하여 data와 매칭되지 않는 기존 DOM 요소를 반환합니다. 이러한 요소는 보통 더 이상 필요하지 않아서 제거하는 데 사용됩니다.

selection.datum(value)

선택된 각 요소에 대해 바인딩된 데이터를 가져오거나 설정합니다. selection.data와 달리 join을 계산하지 않으며 인덱스나 enter와 exit 선택 항목에 영향을 미치지 않습니다. data는 하나하나 개별로 들어가는 느낌이라면 datum은 리스트 전체로 하나의 data를 구성하는 느낌입니다.

selection.merge(other)

현재 선택된 요소와 지정된 다른 선택 항목을 병합하여 새로운 선택 항목을 반환합니다. 반환된 선택 항목은 동일한 그룹 수와 동일한 부모 요소를 가지며, 현재 선택 항목의 누락된 요소는 지정된 선택 항목으로 채워집니다.