Розуміння того, як D3.js прив’язує дані до вузлів


75

Я читаю через документацію D3.js, і я знайти його важко зрозуміти , на selection.dataметод з документації.

Це приклад коду, наведеного в документації:

var matrix = [
  [11975,  5871, 8916, 2868],
  [ 1951, 10048, 2060, 6171],
  [ 8010, 16145, 8090, 8045],
  [ 1013,   990,  940, 6907]
];

var tr = d3.select("body").append("table").selectAll("tr")
    .data(matrix)
  .enter().append("tr");

var td = tr.selectAll("td")
    .data(function(d) { return d; })
  .enter().append("td")
    .text(function(d) { return d; });

Я більшу частину цього розумію, але що відбувається з .data(function(d) { return d; })розділом var tdзаяви?

Моє найкраще здогадування таке:

  • Оператор var trприв’язав чотириелементний масив до кожного вузла tr
  • Потім цей var tdвираз якось використовує цей чотириелементний масив як свої дані

Але як .data(function(d) { return d; })насправді отримувати ці дані і що вони повертають?


3
Це може допомогти прочитати цей підручник .
Phrogz

Дякую! Тепер я розумію, що відбувається з .enter()частинами коду. Думаю, мені, можливо, доведеться почекати майбутнього підручника, щоб зрозуміти, що відбувається з функцією ключа даних.
Річард

4
Я сподіваюся незабаром написати новий підручник, який охоплює ключову функцію, а також ієрархічні виділення (selectAll.selectAll).
mbostock 01.03.12

Відповіді:


69

Коли ви пишете:

….data(someArray).enter().append('foo');

D3 створює купу <foo>елементів, по одному для кожного запису в масиві. Що ще більш важливо, він також пов'язує дані кожного запису в масиві з цим елементом DOM як __data__властивість.

Спробуйте це:

var data = [ {msg:"Hello",cats:42}, {msg:"World",cats:17} ]; 
d3.select("body").selectAll("q").data(data).enter().append("q");
console.log( document.querySelector('q').__data__ );

Те, що ви побачите (у консолі) - це об’єкт {msg:"Hello",cats:42}, оскільки це було пов’язано з першим створеним qелементом.

Якщо ви пізніше зробите:

d3.selectAll('q').data(function(d){
  // stuff
});

цінність dвиявляється цією __data__властивістю. (На даний момент вам потрібно забезпечити заміну // stuffкодом, який повертає новий масив значень.)

Ось ще один приклад, що показує дані, прив’язані до елемента HTML, і можливість повторного прив’язки підмножин даних до нижчих елементів:

  без опису


20

Ключем до розуміння того, що робить цей код, є визнання того, що виділення є масивами масивів елементів DOM. Самий зовнішній масив називається "виділенням", внутрішній масив (масиви) називається "групами", і ці групи містять елементи DOM. Ви можете перевірити це, зайшовши в консоль на d3js.org і зробивши виділення типу d3.selectAll ('p'), ви побачите масив, що містить масив, що містить елементи 'p'.

У вашому прикладі при першому виклику selectAll ('tr') ви отримуєте виділення з однією групою, яка містить усі елементи 'tr'. Потім кожен елемент з matrixузгоджується з кожним елементом "tr".

Але коли ви викликаєте selectAll ('td') на цьому виділенні, виділення вже містить групу елементів 'tr'. Цього разу кожен із цих елементів стане групою елементів td. Група - це просто масив, але вона також має властивість parentNode, яка посилається на старий вибір, в даному випадку на елементи 'tr'.

Тепер, коли ви викликаєте data(function(d) { return d; })цей новий вибір елементів 'td', dпредставляє дані, прив'язані до батьківського вузла кожної групи. Отже, у прикладі, "td" у першій групі будуть пов'язані з масивом [11975, 5871, 8916, 2868]. Друга група "тд" пов'язана з [1951, 10048, 2060, 6171].

Ви можете прочитати власне чудове пояснення вибору та прив'язки даних Майка Бостока тут: http://bost.ocks.org/mike/selection/


Дякую! Я думаю, що ця відповідь дуже чітка, переходить прямо до суті; більше, ніж інша відповідь (яка також пропонує корисну інформацію, без образ)
дроти

Завдяки посиланню Кім. Це досить детально, щоб я зрозумів. Далі це підштовхнуло мене до bost.ocks.org/mike/nest
VivekDev

2
Хоча коментар Фрогза має чудову інформацію та дуже корисний, ця відповідь чітко пояснює точне поставлене запитання. У мене була та ж плутанина, і вона клацнула, коли побачила частину, яка return d;повертає батьківський вузол. Плутанина полягає в тому, що певні методи працюють на різних ієрархічних рівнях. Наприклад, attrпрацює на окремих елементах, на відміну від data. Дякую!
Mike Williamson,

1

Використовуйте лічильник i, щоб показати індекс використовуваних даних.

var tr = d3.select("body").append("table").selectAll("tr")
.data(matrix)
.enter().append("tr") //create a row for each data entry, first index
.text(function(d, i) { return i}); // show the index i.e. d[0][] then d[1][] etc.

var td = tr.selectAll("td")
.data(function(d) { return d; })
.enter().append("td")
.style("background-color", "yellow") //show each cell
.text(function(d,i) { return i + " " + d; }); // i.e d[from the tr][0] then d[from the tr][1]...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.