Я создаю сеть с направленной силой в D3, где каждый узел представляет собой веб-страницу в коллекции, а направленные ссылки между ними представляют собой гиперссылку с одной веб-страницы на другую. Когда пользователь перемещается между веб-страницами, ссылки добавляются в сеть. Количество узлов/веб-страниц в коллекции не изменяется.Позиции узла NaN после установки начального положения в сети с принудительной силой d3
Всякий раз, когда добавляется новая ссылка, я перезагружаю сеть, считывая код JSON, содержащий новые и старые ссылки и все узлы. На данный момент я пытаюсь «успокоить» первоначальную загрузку этой сети, чтобы узлы не создавались в произвольных местах, потенциально создавая сеть, где узлы нигде не находятся рядом с ними. Для этого я хочу установить начальную позицию каждого узла в том, что было в предыдущей сети.
Я сделал это путем установки х и у атрибутов узла как показано в следующем фрагменте кода:
var links = data.links;
var nodes = data.nodes;
var nodeDictionary = new Object();
if (node != 0) {
force.stop();
node.each(function(d) {
var pos = [];
var thisNode = d3.select(this);
pos[0] = thisNode.attr("x");
pos[1] = thisNode.attr("y");
var page = thisNode.attr("page");
nodeDictionary[page] = pos;
});
nodes.forEach(function(node) {
var x = nodeDictionary[node.id][0];
var y = nodeDictionary[node.id][1];
//node.px = undefined;
//node.py = undefined;
node.x = x;
node.y = y;
});
}
Это, кажется, работает некоторое время или для некоторых узлов, но большую часть времени это приводит к узлам, имеющим позиции NaN. В частности, эти позиции NaN в методе клеща() сетей, которая выглядит следующим образом:
// Animates the force-directed network
function tick() {
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
link.attr("d", drawCurve);
}
function drawCurve(d) {
var testing = "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y;
return testing
}
В других примерах я видел, где начальное положение узла устанавливается в силовой направленной сети, тик() метод выглядит так:
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
есть ли что-то еще мне нужно сделать, чтобы мой код работы с помощью функции перевода? Я попытался остановить метод тика перед созданием новой сети, как было предложено в этом потоке https://groups.google.com/forum/#!topic/d3-js/k6VSYZfMjGA, но это не помогло. Нужно ли мне очищать некоторую переменную или элемент перед созданием новой сети? Я также попытался установить атрибуты px и py и атрибуты px, py, x и y с различными комбинациями значений без успеха.
Я создал jsfiddle с базовым кодом, показывающим проблему, с которой я столкнулся: http://jsfiddle.net/ew5qprhe/1/ Двойной щелчок по любому из узлов вызовет создание новой сети. Некоторые из узлов правильно настроены на их предыдущие позиции, но одни с позициями NaN перемещаются в верхний левый угол.
Этот фрагмент кода серьезно испорчен, но я предполагаю, что свойство 'id' в вашем наборе данных не всегда равно атрибуту« страница », который вы извлекаете из элементов''. –
Извините за странный код. Атрибут страницы должен соответствовать идентификатору. Выполняя быстрый тест, похоже, что каждому узлу назначаются x и y, как и ожидалось. Позиция, хранящаяся в nodeDictionary с использованием атрибута страницы, соответствует позиции, назначенной узлу с идентификатором соответствия. – silentfuzzle