d3 sankey charts - позиционировать узел вручную по оси X

Проблема, с которой я столкнулся при использовании реализации d3 sankey, заключается в том, что невозможно указать, где по оси x находится узел. Я копался в исходниках, и на самом деле нет «чистого» способа указать значение x в разумной шкале (т. е. 1-5, когда диаграмма имеет ширину 5 узлов). Я создаю что-то, что можно использовать как планировщик курсов для образования, поэтому значение x будет соответствовать семестру. Предположим, у меня есть курс, который я не могу пройти до второго года обучения в колледже, это будет x из 3 (1/2 — первокурсник, 3/4 — второкурсник и т. д.). Проблема в том, что если нет ничего, что ссылалось бы на этот курс заранее, он всегда будет иметь значение x, равное 1, поэтому я хотел бы сдвинуть его на два пробела вправо.

Я заметил, что значение x на фактической диаграмме Санки не отражает количество узлов на ней, поэтому это немного сложно сделать.

Я также столкнулся с этот вопрос, и я понимаю, что по умолчанию диаграмма не позволяет мне расположить узел. У меня нет проблем с настройкой примера sankey.js для достижения этой цели, но в настоящее время я не знаю, как это сделать.


person Seiyria    schedule 03.02.2014    source источник
comment
Для этого есть билет: github.com/d3/d3-plugins/issues/88.   -  person Thilo    schedule 21.03.2014
comment
Спасибо за открытие @Thilo!   -  person Seiyria    schedule 21.03.2014


Ответы (4)


Это возможно. См. этот JSFiddle.

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

Функцию computeNodeBreadths в sankey.js можно изменить так, чтобы она искала явную x-позицию, назначенную узлу (node.xPos):

  function computeNodeBreadths() {
    var remainingNodes = nodes,
        nextNodes,
        x = 0;

    while (remainingNodes.length) {
      nextNodes = [];
      remainingNodes.forEach(function(node) {

        if (node.xPos)
            node.x = node.xPos;
        else
            node.x = x;

        node.dx = nodeWidth;
        node.sourceLinks.forEach(function(link) {
          nextNodes.push(link.target);
        });
      });
      remainingNodes = nextNodes;
      ++x;
    }

    //
    moveSinksRight(x);
    scaleNodeBreadths((width - nodeWidth) / (x - 1));
  }

Затем все, что вам нужно сделать, это указать xPos на нужных узлах. В приведенном выше примере я установил xPos = 1 на node2. См. getData() в примере JSFiddle:

... }, {
        "node": 2,
        "name": "node2",
        "xPos": 1
    }, { ...
person Greg Ross    schedule 04.02.2014
comment
Спасибо. Я попробовал это, но, думаю, мне нужно было сделать еще несколько настроек в моем наборе данных, чтобы он действительно работал. Ваш пример подтвердил это и очень помог мне! - person Seiyria; 05.02.2014
comment
@ Грег Росс - спасибо за решение. Есть ли способ настроить раковины так, чтобы они НЕ находились с правой стороны svg? Я заметил, что не могу переопределить позицию узла 3 в вашем JSFiddle: jsfiddle.net/88Akd. Спасибо. - person NickBraunagel; 17.11.2016
comment
Привет @NickBraunagel - Хорошее место. Если вы закомментируете moveSinksRight(x); в строке 137 в скрипаче, вы можете разместить узел приемника там, где вам нравится. - person Greg Ross; 18.11.2016

Если кто-то будет искать, как исправить начальное положение развернутых узлов (прямоугольников), вы можете сделать это:

sankey.layout = function(iterations) {
    computeNodeLinks();
    computeNodeValues();
    computeNodeBreadths();
    computeNodeDepths(iterations);
    computeAbsolutePositions(); // add this in sankey.js file
    computeLinkDepths();
    return sankey;
};

И добавляем сами позиции:

function computeAbsolutePositions() {
    nodes[0].x = 0;
    nodes[0].y = 0;
    nodes[1].x = 260;
    nodes[1].y = 0;
};

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

Надеюсь, что это может помочь кому-то!

person Andrey    schedule 24.04.2015

Назовем координату x layer. layer=0 будет левым краем, а layer=n будет правым краем. В файле JSON в поле nodes добавьте пару ключ-значение layer: your_desired_x_as_integer.

Затем откройте файл sankey.js и найдите функцию componentsByBreadth.forEach. Замените строку node.x = component.x + node.x; на:

if (node.layer) node.x=node.layer;
else node.x = component.x + node.x;

Вы также можете определить плотность таких слоев, например. узлы, размещенные на слоях 0,1,2 или 0,4,8, будут иметь центральный узел и два по краям ширины санкея, а 0,1,5 не будут иметь.

Если вам нужна дополнительная помощь, эта функция, среди многих других, включена в мое приложение D3 Sankey: http://sankey.csaladen.es

person csaladenes    schedule 01.05.2015

может быть не тот чистый ответ, который вам нужен, но вы можете явно изменить исходный и целевой атрибуты x, а затем обновить ссылки

http://bl.ocks.org/danharr/af796d91926d254dfe99

person Dan Harrington    schedule 30.10.2014