Подтвердить что ты не робот

D3js: создать новые родительские данные в дочерние узлы

Я не могу решить, как лучше передать изменения в данные, которые происходят у родительского node (например, SVG g), вплоть до него (например, SVG circle).

Я читал этот и этот, но до сих пор не могу понять.

Вот минимальный рабочий пример. В примере предполагается, что у вас есть объект с именем svg, который ссылается на выбор d3, содержащий элемент SVG.

data = [{"id":"A","name":"jim"},{"id":"B","name":"dave"},{"id":"C","name":"pete"}];

g = svg.selectAll("g").data(data, function(d) { return d.id; }).enter().append("g");

g.append("circle")
      .attr("r", 3)
      .attr("cx", 100)
      .attr("cy", function(d,i) {return 100 + (i * 30);})

// The data gets passed down to the circles (I think):
console.log("circle data:");
d3.selectAll("g circle").each(function(d) { console.log(d.name); });     

// Now change the data, and update the groups' data accordingly
data = [{"id":"A","name":"carol"},{"id":"B","name":"diane"},{"id":"C","name":"susan"}];
svg.selectAll("g").data(data, function(d) { return d.id;});

// These are the results of the change:
console.log("after change, the group has:");
d3.selectAll("g").each(function(d) { console.log(d.name); });     
console.log("but the circles still have:");
d3.selectAll("g circle").each(function(d) { console.log(d.name); });   

Может ли кто-нибудь помочь мне найти краткий способ получить новые имена во всех дочерних элементах группы? В моем реальном примере каждый g содержит много circle s.

4b9b3361

Ответ 1

Существует два способа распространения данных от родителей к детям:

  • selection.select будет делать это неявно. (Реализации selection.append и selection.insert на самом деле основаны на selection.select внутри)

    svg.selectAll("g").select("circle")
    
  • Вы можете явно переписать соединение данных с помощью функции для получения родительских данных и вернуть ее в массив для дочернего элемента.

    svg.selectAll("g").selectAll("circle")
        .data(function(d) { return [d]; });
    

Эти суммы равны. Первый вариант зависит от какого-то особого поведения при выборе, поэтому сначала может показаться немного удивительным, но приятно, что шаблон для node обновляется симметрично с шаблоном для создания node с помощью insert/append. Второй вариант полезен, если вам нужно применить какие-либо изменения к данным по мере их распространения.

Здесь также может быть полезной и другая статья, которую вы не могли бы связать с ней: Мышление со вставками

Ответ 2

Не уверен, что вы это поняли, но это определенно не в документации. Вся документация, связанная с группировкой элементов, по-видимому, не касается выбора дочерних элементов и наследования данных для детей.

Ответ заключается в том, чтобы использовать конструкцию .each для обновления дочерних элементов и добавления дочерних элементов в вызов группы enter().

data = [{"id":"A","name":"jim"},{"id":"B","name":"dave"},{"id":"C","name":"pete"}];

function draw(data) {
  var g = svg.selectAll("g").data(data, function(d) { return d.id; })

  genter = g.enter().append("g");

  // This is the update of the circle elements - 
  // note that it is attached to the g data, not the enter()
  // This will update any circle elements that already exist
  g.each(function(d, i) {
    var group = d3.select(this);
    group.select("circle")
    .transition() 
      .attr("r", 3)
      .attr("cx", 100)
      .attr("cy", function(d,i) {return 100 + (i * 30);})
  }

  // The data DOES get passed down to the circles, and the enter() statement
  // will create a circle child for each data entry
  genter.append("circle")
      .attr("r", 3)
      .attr("cx", 100)
      .attr("cy", function(d,i) {return 100 + (i * 30);})
}

// Original drawing
draw(data);

// Now change the data, and update the groups' data accordingly
data = [{"id":"A","name":"carol"},{"id":"B","name":"diane"},{"id":"C","name":"susan"}];

// Second drawing, the SVG will be updated
draw(data);

Сообщите мне, если это сработает.

[Этот ответ основан на некоторой группировке кода из этого сообщения coderwall: https://coderwall.com/p/xszhkg]