2013-10-05 2 views
1

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

  1. Когда страница HTML загружена, будет один узел в фиксированном месте. Скажем, верхний левый. Назовем его узлом шаблона, и этот узел не движется.

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

  3. В любое время пользователь должен иметь возможность перемещать узел. И снова узел должен оставаться там, где пользователь покидает его.

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

  5. Когда связь проведена между двумя узлами, узлы не должны менять позиции.

  6. Когда два узла связаны друг с другом и один из них перемещается путем перетаскивания его, тогда ссылка должна измениться по размеру и ориентации по мере необходимости.


Я использую макет силы.

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

Я могу создать ссылки и новые узлы. Но узлы перемещаются и связывают изменение размера. Возможно, это связано с тем, что силовая компоновка пытается сделать длину ссылки равной расстоянию линии в макете силы. Но я не знаю, как использовать функцию для расстояния связи? Я даже не уверен, что это действительно поможет.

Какой метод следует использовать? Есть идеи?

+0

Это звучит, как вы не хотите использовать для этого силовую компоновку. –

+0

Благодарим за отзыв. Это мой второй вопрос. Я опубликовал это, потому что я чувствовал, что это существенно отличается от моего предыдущего вопроса. Какую компоновку я должен использовать? – Avinash

ответ

1

Для силовой компоновки вы можете установить свойство «fixed» узла в true, чтобы предотвратить его влияние на симуляцию. После этого вы сможете установить его вручную. Вы можете выбрать, чтобы сделать это в вызове функции:

function pinNode(node) { 
    node.fixed = true; 
} 

function unpinNode(node) { 
    node.fixed = false; 
} 

Я считаю, что вы могли бы получить узел в левом верхнем углу с вызовом, как это: pinNode(node, 0, 0) . Пока узел имеет фиксированное свойство, равное true, он должен оставаться незатронутым симом. Вы можете найти этот фрагмент из документации полезной; он описывает, как фиксированное свойство влияет force.drag:

Bind поведение к узлам, чтобы интерактивное перетаскивание, либо с помощью мыши или сенсорного экрана. Используйте это совместно с оператором вызова на узлах; например, скажем, node.call (force.drag) при инициализации. Событие перетаскивания устанавливает фиксированный атрибут узлов при наведении курсора мыши, такой как , что, как только мышь над узлом, он перестает двигаться.Фиксация на mouseover, а не на mousedown, облегчает уловку перемещения узлов. Когда принимается событие mousedown и на каждом последующем mousemove до мыши, центр узла устанавливается на текущую мышь . Кроме того, каждый mousemove запускает возобновление силы компоновки, повторно нагревая симуляцию. Если вы хотите, чтобы перетаскиваемые узлы оставались фиксированными после перетаскивания, установите фиксированный атрибут в true на dragstart, как в примере макета липкой силы.

force.drag

Также смотрите здесь: force layout nodes

Если вы хотите использовать функцию расстояния связи, включите его при создании макета силы:

var force = d3.layout.force() 
    .size(width, height) 
    .linkStrength(0.5) // how much can link distance be overridedn by the simulation 
    .linkDistance(function() {return /* some evaluation */;}); 

// ... 

// You might need to defer the calculation of linkDistance until later, 
// such as in update(), since nodes might not have the properties 
// that you need to check until that point: 

function update() { 
    force 
    .nodes(nodes) 
    .links(links) 
    .linkDistance(function(link) { 
     // The function gets called for each link in the simulation. 
     // Each link will be connected to two nodes, source and target, 
     // which may be useful in determining link distance. 
     if (link.source.someProperty || link.target.somePropery) { 
     return /* something */; 
     } else { 
     return /* something else */; 
     } 
    }); 
} 
+0

Отредактирован ответ, чтобы включить отложенный расчет для linkDistance, вызывая его в update(). –

+0

Спасибо, но я все еще могу решить эту проблему. См. http://bl.ocks.org/rkirsling/5001347 В настоящее время узел перемещается, когда пользователь удерживает клавишу ctrl и перетаскивает узел. Но он также движется сам по себе. своя. Какие изменения кода необходимо сделать для достижения следующего? Узел не должен двигаться сам по себе. Он должен двигаться только тогда, когда пользователь ctrl перетащит его. Когда узел создается, он должен оставаться там, где он создается. Когда узел перемещается пользователем, он должен оставаться там, где пользователь покидает его. – Avinash

+0

Когда пользователь перемещает один узел, другие узлы не должны менять свои позиции. Когда два узла связаны, они не должны менять позиции. Любая идея? Благодарю. – Avinash