d3.js :`join`을 사용한 업데이트로 중첩 선택

Sep 02 2020

저는 d3.js를 처음 사용하고 중첩 된 선택으로 업데이트를 지원 하는 selection-join 과 유사한 것을 복제하려고합니다 . 나는 명시 적 /를 사용하여 이전 버전에 대해이 질문 을 보았고 그것을 수정하려고했습니다. 그러나이 코드로 내부 바인딩을 파악할 수 없습니다. 예를 들어 상위 반복 소문자는 반복에서 변경되지 않는 간격이 아니라 후속 간격에서 분홍색입니다. CodePenenterexitn-1

const main = d3.select("main");

function updateOld() {
  content = randomUpper().map(u => {
    return {
      header: u,
      list: randomLower()
    };
  });

  let outer = main.selectAll("div")
    .data(content, d => d.header)
  outer.exit().remove();

  const outerEnter = outer.enter()
    .append("div")
    .style("color", "green")
    .text(d => d.header);

  outer = outerEnter.merge(outer.style("color", "gray"));

  inner = outer.selectAll("h6")
    .data(d => d.list);
  inner.exit().remove();

  inner.enter()
    .append("h6")
    .style("color", "blue")
    .merge(inner.style("color", "pink"))
    .text(d => d);
}

setInterval(updateOld, 2000);
updateOld();

function randomUpper() {
  return d3.shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""))
    .slice(0, Math.floor(6 + Math.random() * 20))
    .sort();
}

function randomLower() {
  return randomUpper().map(u => u.toLowerCase())
}
main {
  display: flex;
}

div {
  width: 40px;
}

h6 {
  margin: 5px 0;
}
<main></main>
<script src="https://d3js.org/d3.v6.js"></script>

이상적으로는 v6 join(가능한 경우) 을 활용하기 위해 이것을 조정하고 싶습니다 . 이것은 내가 가진 가장 가까운 방법이지만 데이터 바인딩 및 선택을 관리하는 올바른 방법을 파악할 수 없습니다.

function updateV6() {
  content = randomUpper().map(u => {
    return { header: u, list: randomLower() };
  });

  main.selectAll("div")
    .data(content, d => d.header)
    .join(
      enter => {
        root = enter.append("div")
        
        root.append("h3")
          .style("color", "green")
          .text(d => d.header);
        
        root.selectAll("h6")
          .data(d => d.list)
          .join("h6")
            .style("color", "blue")
            .text(d => d);
      },
      update => {
        update.selectAll("h3")
          .style("color", "gray")

        // How to add the newly introduced h6 elements corresponding
        // to each h3 and change color of others that remain across iterations?
      }
    );
}

답변

1 RubenHelsloot Sep 03 2020 at 01:14

에서 돌아 왔는지 확인 하여 이러한 다른 작업 ( enter및 이후 update)을 결합 할 수 있습니다 . 선택 항목을 반환하면 병합 할 수 있으며 그 후에 모두 동일하게 처리 할 수 ​​있습니다..join()

  • 새 값을 입력하여 분홍색으로 만듭니다.
  • 기존 값을 업데이트하여 파란색으로 만듭니다.
  • 모든 값에 올바른 텍스트 제공

편집 : 두 번째 .data()부분 에서 핵심 기능이 누락되어 d3가 색인 대신 문자 값을 볼 수 있다고 생각합니다 . 나는 당신의 cycle기능을 사용하여 더 명확하게 만들었습니다.

const main = d3.select("main");

const cycle = [
  [{
      header: "B",
      list: ["a", "b", "c"]
    },
    {
      header: "C",
      list: ["c"]
    },
  ],
  [{
      header: "B",
      list: ["a", "c", "d", "e"]
    }, // remove [b], add [d,e]
    {
      header: "D",
      list: ["a", "b", "c", "d"]
    },
  ],
  [{
      header: "D",
      list: ["b", "c", "e"]
    }, // remove [a, d], add [e]
    {
      header: "E",
      list: ["a", "b", "c"]
    },
  ],
]

var counter = 0;

function updateV6() {
  content = cycle[counter % cycle.length];
  counter++;

  main.selectAll("div")
    .data(content, d => d.header)
    .join(
      enter => {
        root = enter.append("div")
        root.append("h3")
          .style("color", "green")
          .text(d => d.header);
        return root;
      },
      update => {
        update.selectAll("h3")
          .style("color", "gray");
        return update;
      }
    )
    .selectAll("h6")
    .data(d => d.list, d => d)
    .join(
      enter => enter.append('h6').style("color", "blue"),
      update => update.style("color", "pink")
    )
    .text(d => d);
}

setInterval(updateV6, 2000);
updateV6();
main {
  display: flex;
}

div {
  width: 40px;
}

h6 {
  margin: 5px 0;
}
<main></main>
<script src="https://d3js.org/d3.v6.js"></script>