2014-10-20 4 views
1

Я создаю сеть с направленной силой в 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 перемещаются в верхний левый угол.

+0

Этот фрагмент кода серьезно испорчен, но я предполагаю, что свойство 'id' в вашем наборе данных не всегда равно атрибуту« страница », который вы извлекаете из элементов' '. –

+0

Извините за странный код. Атрибут страницы должен соответствовать идентификатору. Выполняя быстрый тест, похоже, что каждому узлу назначаются x и y, как и ожидалось. Позиция, хранящаяся в nodeDictionary с использованием атрибута страницы, соответствует позиции, назначенной узлу с идентификатором соответствия. – silentfuzzle

ответ

2

Ключ в том, чтобы изменить этот бизнес:

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; 
}); 

к этому:

node.each(function(d) { 
    pos = []; 
    pos[0] = d.x; 
    pos[1] = d.y; 
    var page = d.id; 
    nodeDictionary[page] = pos; 
}); 

Странные вещи происходили из-за моего использования .attr ("х") и .attr (» у "). Кроме того, прокляните мою незнакомость с D3!

+0

Хмм, я, должно быть, получаю «NaN» по другой причине. Обратите внимание, что первые три строки могут быть записаны как 'pos = [d.x, d.y]'. – harpo