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

Динамическое изменение размера дерева d3 на основе количества дочерних узлов

Из этого примера http://mbostock.github.com/d3/talk/20111018/tree.html Я построил d3 tree layout, где корень находится в середине (root.x0 = width/2) в окне браузера, а узлы находятся в нисходящем направлении, а не обращены вправо.

Можно ли изменить размер дерева таким образом, чтобы ширина дерева зависела на число узлов дерева, такое, что если число узлов меньше, то ширина меньше или если число узлов больше, то ширина велика?

Мне также нужно знать, как d3 tree layout вычисляет в настоящее время атрибут d.x? Как я могу манипулировать атрибутом "d.x" для настройки расстояния между узлами макета дерева d3.

4b9b3361

Ответ 1

Поэтому, когда вы устанавливаете "размер" макета дерева, все, что вы делаете, - это значение, которое макет дерева будет интерполировать значения x и y. Поэтому нет причин, по которым вы не можете вычислить требуемую ширину или высоту и изменить их в макете при каждом вызове обновления.

Я скопировал пример, который вы передали jsFiddle, и добавил следующую функцию обновления:

// compute the new height
var levelWidth = [1];
var childCount = function(level, n) {

  if(n.children && n.children.length > 0) {
    if(levelWidth.length <= level + 1) levelWidth.push(0);

    levelWidth[level+1] += n.children.length;
    n.children.forEach(function(d) {
      childCount(level + 1, d);
    });
  }
};
childCount(0, root);  
var newHeight = d3.max(levelWidth) * 20; // 20 pixels per line  
tree = tree.size([newHeight, w]);

Обратите внимание, что это довольно грубый расчет и не учитывает, где дети являются w.r.t их родителями или чем-то еще, но вы получаете идею.

Что касается манипулирования значениями x узлов, проще всего просто изменить узлы после того, как макет сделал это. Фактически вы можете видеть, что это уже сделано в примере с координатой y:

// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; }); 

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

Что касается сверху вниз, я думаю, что вы можете просто перевернуть всюду, где увидите x и y (и x0 и y0). Не забудьте сделать то же самое с диагональной проекцией, чтобы убедиться, что ваши линии тоже переворачиваются.