d3.js: "join" kullanan güncellemeyle İç İçe Seçim

Sep 02 2020

D3.js'de yeniyim ve iç içe seçimlerle güncellemeleri destekleyen seçim-birleştirmeye benzer bir şeyi kopyalamaya çalışıyorum . Gördüğüm bu soruyu açık olan önceki sürümleri için / ve onu adapte çalıştı. Ancak, bu kodla iç bağlamayı tam olarak anlayamıyorum. Örneğin, en üstteki küçük harfli harfler, yinelemelerde değişmeyenler yerine sonraki aralıklarda pembedir. 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>

İdeal olarak, bunu v6'dan yararlanmak için uyarlamak isterim join(mümkünse). Elimdeki en yakın şey bu ancak veri bağlamayı ve seçimleri yönetmenin doğru yolunu tam olarak bulamıyorum.

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?
      }
    );
}

Yanıtlar

1 RubenHelsloot Sep 03 2020 at 01:14

Sen (sonra bu farklı işlemleri birleştirebilir enterve updateemin yaparak) return dan .join(). Seçimlerin geri döndürülmesi, bunların birleştirilmesine olanak tanır, ardından hepsine aynı şekilde davranabilirsiniz:

  • pembe yapmak için yeni değerler girin
  • mevcut değerleri mavi yapmak için güncelleyin
  • tüm değerlere doğru metni verin

Düzenleme: İkinci .data()bölümünüzde d3'ün harflerin indeksleri yerine değerlerine bakmasını sağlayacak bir anahtar işlevi eksik olduğunu düşünüyorum . Daha cyclenet hale getirmek için işlevselliğini kullandım .

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>