D3 v4缺少节点

问题描述:

我是D3库(v4)的新手,我需要构建几个强制直接布局。 重复使用[https://bl.ocks.org/mbostock/4062045][1]中的代码我已经用几个矩形节点和里面的文本构建了一个测试。实际上有13个节点有一些链接。然而,虽然绘制了“节点0”的链接,但该布局仅显示了12个节点(从“节点1”到“节点12”)。 DOM看起来只显示12和12,而console.log()正确列出了13个节点对象和文本标签。请有人解释一下我下面的代码中有什么不正确的地方。D3 v4缺少节点

var graph = { "nodes": 
    [{"id":"Node 0","group":2},{"id":"Node 1","group":2}, 
    {"id":"Node 2","group":2},{"id":"Node 3","group":2}, 
    {"id":"Node 4","group":2},{"id":"Node 5","group":2}, 
    {"id":"Node 6","group":2},{"id":"Node 7","group":2}, 
    {"id":"Node 8","group":2},{"id":"Node 9","group":2}, 
    {"id":"Node 10","group":2},{"id":"Node 11","group":2}, 
    {"id":"Node 12","group":4}], 
    "links": 
    [{"source":"Node 0","target":"Node 1","value":"5"}, 
    {"source":"Node 1","target":"Node 5","value":"5"}, 
    {"source":"Node 2","target":"Node 1","value":"5"}, 
    {"source":"Node 3","target":"Node 2","value":"5"}, 
    {"source":"Node 3","target":"Node 1","value":"5"}, 
    {"source":"Node 3","target":"Node 5","value":"5"}, 
    {"source":"Node 4","target":"Node 3","value":"5"}, 
    {"source":"Node 4","target":"Node 8","value":"5"}, 
    {"source":"Node 5","target":"Node 8","value":"5"}, 
    {"source":"Node 6","target":"Node 9","value":"5"}, 
    {"source":"Node 7","target":"Node 3","value":"5"}, 
    {"source":"Node 8","target":"Node 10","value":"5"}, 
    {"source":"Node 9","target":"Node 10","value":"5"}, 
    {"source":"Node 9","target":"Node 7","value":"5"}, 
    {"source":"Node 10","target":"Node 12","value":"20"}, 
    {"source":"Node 11","target":"Node 7","value":"5"}] 
    }; 

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

    var color = d3.scaleOrdinal(d3.schemeCategory20).domain(d3.range(1,20));; 

    var simulation = d3.forceSimulation() 
     .force("link", d3.forceLink().id(function(d) { return d.id; }).distance(100)) 
     .force("charge", d3.forceManyBody()) 
     .force("center", d3.forceCenter(width/2, height/2)); 

    var link = svg.append("g") 
    .attr("class", "links") 
    .selectAll("line") 
    .data(graph.links) 
    .enter().append("line") 
    .attr("stroke-width", function(d) { return Math.sqrt(d.value); }); 

    var nodes = svg.selectAll("g")  
    .data(graph.nodes) 
    .enter() 
    .append("g"); 

    nodes.append("rect") 
    .attr("class", "nodes") 
    .attr("width", 70) 
    .attr("height", 20) 
    .attr("fill", function(d) { return color(d.group); }) 
    .call(d3.drag() 
     .on("start", dragstarted) 
     .on("drag", dragged) 
     .on("end", dragended)); 

    nodes.append("text") 
    .attr("class", "labels") 
    .attr("dy", "1.5em") 
    .attr("dx", "1.5em") 
    .attr("text-anchor", "start") 
    .text(function(d) { return d.id; }); 

    nodes.selectAll('rect') 
    .attr("width", function(d) {return this.parentNode.getBBox().width+10;}) 

    simulation 
    .nodes(graph.nodes) 
    .on("tick", ticked); 

    simulation.force("link") 
    .links(graph.links); 

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

    nodes.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
    } 

    function dragstarted(d) { 
    if (!d3.event.active) simulation.alphaTarget(0.3).restart(); 
    d.fx = d.x; 
    d.fy = d.y; 
    } 

    function dragged(d) { 
    d.fx = d3.event.x; 
    d.fy = d3.event.y; 
    } 

    function dragended(d) { 
    if (!d3.event.active) simulation.alphaTarget(0); 
    d.fx = null; 
    d.fy = null; 
    } 

在这一行:

var nodes = svg.selectAll("g")  
    .data(graph.nodes) 
    .enter() 
    .append("g"); 

你是 “选择所有组”。但是,运行时,DOM中已经有一个<g>元素(请参阅var link)。因此,您的第一个数据将被绑定到现有的<g>,并且您的输入选择将少一个元素。

解决方案:选择一些不存在

var nodes = svg.selectAll("foo")  
    .data(graph.nodes) 
    .enter() 
    .append("g");