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

Плавное переключение между деревьями, кластером, радиальным деревом и рамочными кластерами

Для проекта мне нужно интерактивно изменять иерархическую структуру данных визуализации - без какого-либо изменения базовых данных. Макеты, способные переключаться между собой, должны быть деревом, кластером, радиальным деревом и радиальным кластером. И переход должен быть предпочтительно анимацией.

Я думал, что это будет относительно простой задачей с D3. Я начал, но я потерялся в переводах и поворотах, привязках данных и т.д., Поэтому я прошу вас о помощи. Кроме того, возможно, я делаю что-то не в духе D3, что плохо, так как я ищу чистое решение.

Я собрал jsfidle, но это всего лишь отправная точка с добавленными переключателями, удобным небольшим набором данных и начальным расположением кластера - чтобы помочь кому-либо который хочет взглянуть на это. Спасибо заранее!

UPDATE:

Я хотел сосредоточиться только на ссылках, поэтому я временно отключил другие элементы. Основываясь на методе @AmeliaBR, получаются следующие анимации:

enter image description here

Вот обновленный jsfiddle.

ОБНОВЛЕНИЕ 2:

Теперь с кругами: (извините, мой выбор цветов)

{дум-Дуба-дум}

enter image description here

Вот еще один обновленный jsfiddle.

4b9b3361

Ответ 1

Я не понимаю, почему это было бы так сложно, если бы все ваши макеты имели одинаковую общую структуру путей ссылок, окружных узлов и текстовых меток.

Просто убедитесь, что все ваши объекты, включая пути ссылок, имеют хороший ключ данных, который не зависит от атрибутов данных, созданных функциями макета. Затем для каждого перехода обновите данные с помощью результатов соответствующей функции макета и нарисуйте этот макет.

У меня есть переход к радиальному дереву, реализованному здесь: http://jsfiddle.net/YV2XX/5/

Key code:

//Radial Tree layout//
var diameter = 500;
var radialTree = d3.layout.tree()
    .size([360, diameter / 2 ])
    .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
var radialDiagonal = d3.svg.diagonal.radial()
    .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
function transitionToRadialTree() {
  var nodes = radialTree.nodes(root), //recalculate layout
      links = radialTree.links(nodes);

    svg.transition().duration(1500)
       .attr("transform", "translate(" + (diameter/2)
                 + "," + (diameter/2) + ")");
             //set appropriate translation (origin in middle of svg)

    link.data(links, function(d){
              return d.source.name + d.target.name;})
      .transition().duration(1500)
      .attr("d", radialDiagonal); //get the new radial path

  node.data(nodes, function(d){
              return d.name ;})
      .transition().duration(1500)
      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; }) 

  node.select("circle")
      .transition().duration(1500)
      .attr("r", 4.5);

  node.select("text")
      .transition().duration(1500)
      .attr("dy", ".31em")
      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d) { return d.x < 180 ? "translate(8)" : "rotate(180)translate(-8)"; });
};

Код макета все из http://bl.ocks.org/mbostock/4063550, я только что изменил его как обновление вместо инициализации.

Также обратите внимание, что я переместил объявление переменной для root вне метода чтения данных, поэтому он может быть повторно доступен с помощью функций перехода.

Макет все еще нуждается в некоторой утонченности, но вы получаете идею.

Теперь, если вы хотите, чтобы один из переходов был разделом, treemap или другим макетом, который не использует структуру node -link, они становятся более сложными...

Ответ 2

У меня недостаточно репутации, чтобы сделать комментарий... так что я просто даю этот крошечный вклад как псевдоответ. Просмотрев этот пост и на основе @VividD прекрасным комментарием о том, насколько простыми оказались переходы, я просто добавил параметр Tree Vertical к преобразованиям в этом fiddle.

Это просто следующее:

var diagonalVertical = d3.svg.diagonal()
    .projection(function (d) { 
        return [d.x, d.y]; 
    });

В любом случае, я отметил это очень учебное взаимодействие.