Почему новые узлы в силовом ориентированном графе D3 не отображаются последовательно?

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

По какой-то причине, когда я добавляю узел назад, он иногда не виден. График перемещается так, как будто узел добавлен, но затем он не отображается. У меня такое ощущение, что он добавляет его, но затем узел снова скрывается в коде force.on("tick"), но я понятия не имею, почему. Я разместил соответствующий код ниже и буду очень признателен за любые идеи! Функция toggleNode определяет, должен ли узел отображаться или скрываться - в основном это просто объединение или добавление в массив узлов. Я храню данные в массиве, называемом набором данных, в котором хранится флаг, указывающий, является ли узел видимым или нет.

var force = d3.layout.force()
.gravity(.05)
.distance(100)
.charge(-100)
.size([w, h]);

var nodes = force.nodes(), links = force.links(); // arrays to hold data

var vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h);         

force.on("tick", function() {

vis.selectAll("circle.node")
    .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

vis.selectAll("line.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; });

});

function restart() {

// UPDATE nodes
var node = vis.selectAll("circle.node")
    .data(nodes, function(d) { return d.id;});

// ENTER new nodes
var nodeEnter = node.enter().append("svg:circle")
        .attr("class", "node")
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; })
        .style("fill", function(d) { return groupColors[(d.group)-1]; })
        .style("stroke","fff")
        .style("stroke-width",1)
        .on("mousedown", function(d) {
            clickNode(d);
            })
        .call(force.drag);

// REMOVE deleted nodes
var nodeExit = node.exit().remove();

force.start();
}

// Add the nodes and links to the vis
function createVis(json) {

    dataset = json; // store data in global

    for (var i = 0; i < dataset['nodes'].length; i++) {
        // fill node info
        nodes.push(dataset['nodes'][i]);
    }

    restart();  
}

// Remove node and associated links.
function toggleNode(nodeKey,eol_id) {

    console.log(nodeKey + ': ' + eol_id);

    var tLabel; // value for toggle label

    if ( dataset['nodes'][nodeKey]['isHidden'] == 0 ) {

        // node is visible, so hide it
        tLabel = 'Show';
        for( var k=0; k<nodes.length; k++ ) {
            if ( nodes[k]['eol_id'] == eol_id ) {
                nodes.splice(k, 1); // remove this node
                break;
            }
        }
        dataset['nodes'][nodeKey]['isHidden'] = 1;
        console.log('node removed: ' + nodeKey);

    } else {

        dataset['nodes'][nodeKey]['isHidden'] = 0;

        nodes.push(dataset['nodes'][nodeKey]);

        tLabel = 'Hide';

    }

    $('#primary_title_toggle').html('&nbsp; <a href="#" onclick="toggleNode(' + nodeKey + ',\'' + eol_id + '\')">' + tLabel + '</a><br>');

    restart();

}

0 ответов

Другие вопросы по тегам