Понимание того, как D3.js связывает данные с узлами - PullRequest
68 голосов
/ 28 февраля 2012

Я читаю документацию по 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 ]

65 голосов
/ 01 марта 2012

Когда вы пишете:

….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и возможность повторного связывания подмножеств данных на нижних элементах:

no description

19 голосов
/ 10 июня 2014

Ключом к пониманию того, что делает этот код, является признание того, что выборки - это массивы массивов элементов 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]. Вторая группа 'td's связана с [1951, 10048, 2060, 6171].

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

1 голос
/ 26 мая 2016

Используйте счетчик 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]...
...