Как создать медленные одновременные переходы нескольких атрибутов в принудительно ориентированных графах?

В предыдущем сообщении под названием "D3: Как создать медленный переход кругов для узлов в Force Directed Graphs FDG?", я получил отличный ответ о том, как перемещать один элемент (например, радиус для «просто круги») в D3.

Мой дополнительный вопрос теперь о том, как одновременно переходить "несколько атрибутов D3"...

Напоминаю, что я использую радиокнопки, сгенерированные D3, для переключения размера узлов в макете FDG (по щелчку мыши) с размера по умолчанию на масштабированную величину. Вы можете найти переключатели в верхнем левом углу диаграммы кластера узлов (http://nounz.if4it.com/Nouns/Applications/A__Application_1.NodeCluster.html)

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

    var densityControlClick = function() {

      var thisObject = d3.select(this);
      var typeValue = thisObject.attr("density_type");
      var oppositeTypeValue = (function() {
        if(typeValue=="On") {
          return "Off";
        } else {
          return "On";
        }
      })();

      var densityBulletSelector = "." + "densityControlBullet-" + typeValue;
      var selectedBullet = d3.selectAll(densityBulletSelector);
      selectedBullet.style("fill", "Black") 

      var oppositeDensityBulletSelector = "." + "densityControlBullet-" + oppositeTypeValue;
      var selectedOppositeBullet = d3.selectAll(oppositeDensityBulletSelector);
      selectedOppositeBullet.style("fill", "White") 

      if(typeValue=="On") {
        var selectedNodeCircles = d3.selectAll("#NODE");
        selectedNodeCircles.transition().duration(500).attr("r", function(d){ return rRange(d.rSize); });
      }
      else {
        var selectedNodeCircles = d3.selectAll("#NODE");            selectedNodeCircles.transition().duration(500).attr("r", function(d) { if (d.id==focalNodeID) { return centerNodeSize; } else { return defaultNodeSize; } } );
      }

    }

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

Мой вопрос: учитывая, что я уже могу успешно переходить радиус кругов, как бы я также переходил другие элементы, такие как длины ребер, на основе таких атрибутов, как «альфа», «трение» и т. д., и... какая теория лежит в основе переход нескольких элементов (другими словами, что означает код на английском языке)? API D3, по-видимому, не дает четкого понимания теории, лежащей в основе одновременного перехода нескольких атрибутов.


person Information Technology    schedule 12.07.2013    source источник
comment
Я отредактировал ваш заголовок. См. Должны ли вопросы включать «теги» в свои заголовки?, если нет единого мнения, не следует.   -  person John Saunders    schedule 12.07.2013


Ответы (1)


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

selectedNodeCircles.transition().duration(500)
    .attr("r", function(d){ return rRange(d.rSize); })
    .attr("stroke", 'red');

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

// This will NOT work
circles.transition().duration(1000).attr('r', 50);
// The radius transition will be overridden by the fill 
// transition and so will not complete
circles.transition().duration(1000).attr('fill', 'red');

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

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

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

В качестве альтернативы, если вы можете подождать, не обновляйте DOM в обратном вызове тика. Позвольте компоновке завершиться — она работает намного быстрее, если не рендерится на каждом такте — и как только она будет завершена, вы можете анимировать атрибуты радиуса и x и y в их окончательные позиции. Конечно, это означает, что вам понадобятся хорошие стартовые позиции.

person Superboggly    schedule 15.07.2013