2015-05-28 12 views
3

У меня есть направленная схема d3 с данными в аналогичной структуре ниже. Можно ли применить к нему разводную схему силы, такую ​​как http://bl.ocks.org/mbostock/1062288? Я хочу, чтобы узел был свернут/развернут по клику.Как создать d3.js Складной силовой макет с данными без дерева?

{ 
    "nodes": [ 
    {"x": 469, "y": 410}, 
    {"x": 493, "y": 364}, 
    {"x": 442, "y": 365}, 
    {"x": 467, "y": 314}, 
    ], 
    "links": [ 
    {"source": 0, "target": 1}, 
    {"source": 1, "target": 2}, 
    {"source": 2, "target": 0}, 
    {"source": 1, "target": 3}, 
    {"source": 3, "target": 2}, 
    ] 
} 

ответ

0

Попробуйте это:

var width = 960,height = 500; 

    var force = d3.layout.force().size([width, height]).charge(-400) 
       .linkDistance(40) 
       .on("tick", tick); 

     var drag = force.drag().on("dragstart", dragstart); 

      var svg = d3.select("body").append("svg").attr("width", width) 
         .attr("height", height); 

      var link = svg.selectAll(".link"), 
        node = svg.selectAll(".node"); 

      d3.json("graph.json", function(error, graph) { 
        force.nodes(graph.nodes).links(graph.links) 
         .start(); 

     link = link.data(graph.links).enter().append("line") 
         .attr("class", "link"); 

        node = node.data(graph.nodes) 
       .enter().append("circle") 
       .attr("class", "node") 
       .attr("r", 12) 
       .call(drag); 
     }); 

     function tick() { 
       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; }); 
      } 



      function dragstart(d) { 
        d3.select(this).classed("fixed", d.fixed = true); 
       } 

Вы должны использовать JSON-файл, как это:

graph.json

 { 
     "nodes": [ 
     {"x": 469, "y": 410}, 
     {"x": 493, "y": 364}, 
     {"x": 442, "y": 365}, 
     {"x": 467, "y": 314}, 
    ], 
     "links": [ 
      {"source": 0, "target": 1}, 
      {"source": 1, "target": 2}, 
      {"source": 2, "target": 0}, 
      {"source": 1, "target": 3}, 
      {"source": 3, "target": 2}, 
     ] 
    } 
+0

Спасибо за ваш ответ, но я ищу для складных и расширяемых узлов мыши. –

+0

Вы ищете такие узлы? (http://bl.ocks.org/mbostock/4339083) – Gabriel

+0

Больше нравится [http://bl.ocks.org/mbostock/1062288](http://bl.ocks.org/mbostock/1062288), но мой json определяется по-разному. –

2

Если я правильно понимаю, возможно, это то, что вы находясь в поиске. Я отредактировал демо, с которым вы связались. Теперь, когда исходный узел свернут, мы перебираем все ребра и ищем другие узлы, к которым он имеет ребра.

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

Когда мы разворачиваем узел, мы делаем то же самое, за исключением того, что мы уменьшаем число свертывания.

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

Я сделал эту работу для ориентированных графиков, хотя я не уверен, что это то, что вы хотели.

Дайте мне знать, что вы думаете!

JSON я использовал:

{ 
    "nodes": [ 
    {"x": 469, "y": 410}, 
    {"x": 493, "y": 364}, 
    {"x": 442, "y": 365}, 
    {"x": 467, "y": 314} 
], 
    "links": [ 
     {"source": 0, "target": 1}, 
     {"source": 1, "target": 2}, 
     {"source": 2, "target": 0}, 
     {"source": 1, "target": 3}, 
     {"source": 3, "target": 2} 
    ] 
} 

Modified учебник код:

<!DOCTYPE html> 
<meta charset="utf-8"> 
<title>Force-Directed Graph</title> 
<style> 

.node { 
    cursor: pointer; 
    stroke: #3182bd; 
    stroke-width: 1.5px; 
} 

.link { 
    fill: none; 
    stroke: #9ecae1; 
    stroke-width: 1.5px; 
} 

</style> 
<body> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script> 

var width = 960, 
    height = 500, 
    root; 

var force = d3.layout.force() 
    .size([width, height]) 
    .on("tick", tick); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

//Added markers to indicate that this is a directed graph 
svg.append("defs").selectAll("marker") 
    .data(["arrow"]) 
    .enter().append("marker") 
    .attr("id", function(d) { return d; }) 
    .attr("viewBox", "0 -5 10 10") 
    .attr("refX", 15) 
    .attr("refY", -1.5) 
    .attr("markerWidth", 4) 
    .attr("markerHeight", 4) 
    .attr("orient", "auto") 
    .append("path") 
    .attr("d", "M0,-5L10,0L0,5"); 

var link = svg.selectAll(".link"), 
    node = svg.selectAll(".node"); 

d3.json("graph.json", function(json) { 
    root = json; 
    //Give nodes ids and initialize variables 
    for(var i=0; i<root.nodes.length; i++) { 
    var node = root.nodes[i]; 
    node.id = i; 
    node.collapsing = 0; 
    node.collapsed = false; 
    } 
    //Give links ids and initialize variables 
    for(var i=0; i<root.links.length; i++) { 
    var link = root.links[i]; 
    link.source = root.nodes[link.source]; 
    link.target = root.nodes[link.target]; 
    link.id = i; 
    } 

    update(); 
}); 

function update() { 
    //Keep only the visible nodes 
    var nodes = root.nodes.filter(function(d) { 
    return d.collapsing == 0; 
    }); 
    var links = root.links; 
    //Keep only the visible links 
    links = root.links.filter(function(d) { 
    return d.source.collapsing == 0 && d.target.collapsing == 0; 
    }); 

    force 
     .nodes(nodes) 
     .links(links) 
     .start(); 

    // Update the links… 
    link = link.data(links, function(d) { return d.id; }); 

    // Exit any old links. 
    link.exit().remove(); 

    // Enter any new links. 
    link.enter().insert("line", ".node") 
     .attr("class", "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; }) 
     .attr("marker-end", "url(#arrow)"); 

    // Update the nodes… 
    node = node.data(nodes, function(d){ return d.id; }).style("fill", color); 

    // Exit any old nodes. 
    node.exit().remove(); 

    // Enter any new nodes. 
    node.enter().append("circle") 
     .attr("class", "node") 
     .attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }) 
     .attr("r", function(d) { return Math.sqrt(d.size)/10 || 4.5; }) 
     .style("fill", color) 
     .on("click", click) 
     .call(force.drag); 
} 

function tick() { 
    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; }); 
} 

// Color leaf nodes orange, and packages white or blue. 
function color(d) { 
    return d.collapsed ? "#3182bd" : d.children ? "#c6dbef" : "#fd8d3c"; 
} 

// Toggle children on click. 
function click(d) { 
    if (!d3.event.defaultPrevented) { 
    //check if link is from this node, and if so, collapse 
    root.links.forEach(function(l) { 
     if(l.source.id == d.id) { 
     if(d.collapsed){ 
      l.target.collapsing--; 
     } else { 
      l.target.collapsing++; 
     } 
     } 
    }); 
    d.collapsed = !d.collapsed; 
    } 
    update(); 
} 

</script> 
+1

Благодарим вас за код. Он работает так, как ожидалось. Дополнительные требования здесь, мне нужно связать узлы по идентификатору узлов вместо индекса, следуя этому примеру [http://stackoverflow.com/questions/23986466/d3-force-layout-linking-nodes-by-na me -instead-оф-индекса] (http://stackoverflow.com/questions/23986466/d3-force-layout-linking-nodes-by-na меня-вместо-оф-индекса). Кроме того, я хочу, чтобы они были привязаны к svg-блоку и добавили текст в узлы. Как мне изменить код? –

+0

@ CY- вы когда-нибудь находили ответ для этого? – Mcestone

+0

Кто-нибудь знает, как это сделать для d3.js v4? – deathlock

 Смежные вопросы

  • Нет связанных вопросов^_^