Плавный переход между макетами дерева, кластера, радиального дерева и радиального кластера

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

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

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

ОБНОВЛЕНИЕ:

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

введите здесь описание изображения

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

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

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

{дум-дуба-дум

введите здесь описание изображения

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


person VividD    schedule 05.01.2014    source источник
comment
Единственное, что мне известно, близко к этому — это ролик. Я сомневаюсь, что вы получите здесь хороший ответ, поскольку для того, чтобы заставить это работать, потребуется довольно много работы.   -  person Lars Kotthoff    schedule 05.01.2014
comment
Я никогда не думал, что это так требовательно.   -  person VividD    schedule 05.01.2014
comment
Возможно, это не так, хотя я подозреваю, что обеспечение плавности переходов может быть немного хлопотным, особенно когда вы выполняете преобразование между евклидовыми и полярными координатами. Так что прямой переход может выглядеть не особенно красиво.   -  person Lars Kotthoff    schedule 05.01.2014
comment
Спасибо за ссылку! Это именно то, что я искал. Я мог бы немного реорганизовать его, если я это сделаю, я опубликую новый jsfiddle! ;-)   -  person netigger    schedule 01.05.2014


Ответы (2)


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

Дополнение просто такое:

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

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

person FernOfTheAndes    schedule 07.01.2014
comment
Превосходно! Вот еще один (jsfiddle.net/VividD/s4Mjx) с .delay( function(d, i) { return 100 * i + 500 * d.source.depth; } ), просто для смеха. - person VividD; 08.01.2014
comment
Технологии встречаются с искусством! - person FernOfTheAndes; 08.01.2014
comment
Все это выглядит действительно здорово — и спасибо за вставку анимации в основной пост @VividD. Действительно демонстрирует потенциал функций компоновки и преимущества общей структуры D3, лежащей в их основе. - person AmeliaBR; 13.01.2014

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

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

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

Ключевой код:

//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 за пределы метода чтения данных, чтобы к нему можно было повторно получить доступ с помощью функций перехода.

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

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

person AmeliaBR    schedule 06.01.2014
comment
Открывающий глаза ответ. Меня здесь больше всего поражает простота решения перехода ссылок, в техническом смысле. Кроме того, я увеличил продолжительность перехода до 15 секунд, и все это выглядит просто великолепно. Я попытаюсь собрать пример на основе вашего метода и вернусь через пару дней с результатом... - person VividD; 06.01.2014