2017-01-13 17 views
2

鉴于以下布局:D3 V4更新,模式的组

<g> 
    ... // many nodes 
    <g> 
     <circle></circle> 
     <text></text> 
    </g> 
    ... 
</g> 

如何将正确的更新模式看起来像D3 V4? (?) 我有什么在合并作为参数使用,多久我得打电话合并

我创建了小提琴的工作示例(仅在节点节点+圆圈+文?):https://jsfiddle.net/cvvfsg97/6/

代码:

function update(items) { 
    node = nodeLayer.selectAll(".node") 
    .data(items, function(d) { return d.id; }) 

    node = node.enter() // insert 
    .append("g") 
    .attr("class", "node"); 

    node.append("circle") // insert 
    .attr("r", 2.5) 
    .attr('class', 'circle') 
    .merge(nodeLayer.selectAll('.node > circle')) // is this correct?! // merge 
    .attr('fill', 'red') // just for testing purposes 
    .exit().remove(); // exit 

    node.append("text") // insert 
     .attr("dy", 3) 
     .text(function(d) { return d.name; }) 
     .merge(nodeLayer.selectAll('.node > text')) // is this correct?! // merge 
     .attr('fill', 'green') // just for testing purposes 
     .exit().remove(); 

    node.merge(nodeLayer.selectAll('.node')) // is this correct?! // merge 
    .attr('class', 'anotherClass') 
    .exit().remove(); // does not work // exit 
} 

有人能带来一些清晰度如何使用输入(条款),合并(),在组退出()?

我很可能喜欢在每个阶段对每个元素进行更改。


更新:我简单的例子,我不需要链接或力布局。我的问题只是关于更新模式,而不是关于力量。更新后的jsfiddle没有强制布局。

+0

你见过https://bl.ocks.org/mbostock/3808218 ?它已更新合并 – softwarenewbie7331

+1

@ Frame91,我很高兴你意识到你有两个不同的问题在这里:一个关于更新模式本身和其他如何更新部队。他们是完全不同的问题。现在的问题是,解决您的一般问题(更新模式)的任何答案都无法正确解决部队问题,因为您现在有两个答案。因此,我建议您删除此问题并发布另一个问题,关于如何为包含文本和圈子的组创建更新模式(并且将很容易回答)。 –

+1

我对力量布局不感兴趣。我只关心更新模式。我只是在jsfiddle上使用了一个现有的例子,它恰好有一个强制布局。对于混淆抱歉;) – Frame91

回答

2

你已经过了复杂的模式。这里是你的更新功能正确写入:

function update(items) { 

    var node = nodeLayer.selectAll(".node") // bind the data, this is update 
    .data(items, function(d) { 
     return d.id; 
    }); 

    node.exit().remove(); // exit, remove the g 

    nodeEnter = node.enter() // enter, append the g 
    .append("g") 
    .attr("class", "node"); 

    nodeEnter.append("circle") // enter, append the circle on the g 
    .attr("r", 2.5) 
    .attr('class', 'circle') 
    .attr('fill', 'red'); 

    nodeEnter.append("text") // enter, append the text on the g 
    .attr("dy", 3) 
    .text(function(d) { 
     return d.name; 
    }) 
    .attr('fill', 'green'); 

    node = nodeEnter.merge(node); // enter + update on the g 

    node.attr('transform', function(d){ // enter + update, position the g 
    return 'translate(' + d.x + ',' + d.y + ')'; 
    }); 

    node.select("text") // enter + update on subselection 
    .text(function(d) { 
     return d.name; 
    }); 

} 

这是多次调用运行:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
</head> 
 

 
<body> 
 
    <script> 
 
    
 
    var nodeLayer = d3.select('body') 
 
     .append('svg') 
 
     .attr('width',500) 
 
     .attr('height',500); 
 
     
 
    update([ 
 
     { 
 
     id: 1, 
 
     name: 'A', 
 
     x: Math.random() * 500, 
 
     y: Math.random() * 500 
 
     },{ 
 
     id: 2, 
 
     name: 'B', 
 
     x: Math.random() * 500, 
 
     y: Math.random() * 500 
 
     },{ 
 
     id: 3, 
 
     name: 'C', 
 
     x: Math.random() * 500, 
 
     y: Math.random() * 500 
 
     } 
 
    ]); 
 
    
 
    setTimeout(function(){ 
 
     update([ 
 
     { 
 
      id: 1, 
 
      name: 'A', 
 
      x: Math.random() * 500, 
 
      y: Math.random() * 500 
 
     },{ 
 
      id: 4, 
 
      name: 'This is a new name...', 
 
      x: Math.random() * 500, 
 
      y: Math.random() * 500 
 
     },{ 
 
      id: 3, 
 
      name: 'C', 
 
      x: Math.random() * 500, 
 
      y: Math.random() * 500 
 
     } 
 
     ]); 
 
    }, 3000); 
 
    
 
    function update(items) { 
 
     
 
     var node = nodeLayer.selectAll(".node") 
 
     .data(items, function(d) { 
 
      return d.id; 
 
     }); 
 
     
 
     node.exit().remove(); // exit, remove the g 
 

 
     nodeEnter = node.enter() // enter the g 
 
     .append("g") 
 
     .attr("class", "node"); 
 
     
 
     nodeEnter.append("circle") // enter the circle on the g 
 
     .attr("r", 2.5) 
 
     .attr('class', 'circle') 
 
     .attr('fill', 'red'); 
 

 
     nodeEnter.append("text") // enter the text on the g 
 
     .attr("dy", 3) 
 
     .attr('fill', 'green'); 
 
     
 
     node = nodeEnter.merge(node); // enter + update 
 
      
 
     node.attr('transform', function(d){ 
 
     return 'translate(' + d.x + ',' + d.y + ')'; 
 
     }); 
 
     
 
     node.select("text") 
 
     .text(function(d) { 
 
     return d.name; 
 
     }); 
 

 
    } 
 
    </script> 
 
</body> 
 

 
</html>

+0

谢谢马克。但是,主要问题仍然存在。如何更新组内的圈子/文字?尽管你提供了一个具体案例的工作示例,但我确实需要更新圈子/文本。我的例子可能会误导人,因为它确实没有必要在那里合并圈子/文本。你可以添加圈/文本更新到你的例子吗? – Frame91

+0

@Frame91,opps,错过了这个用例,查看上面更新的代码片段。您只需选择文本作为enter +更新的子选项。 – Mark

+0

明智的答案 - 正是我所期待的。 – Frame91

-1

我最近在我的代码中完成了这一操作 - 我在包含元素的当前选择中使用select(subSelector)。在您的例子如下我要改变它:

function update(items) { 
var node = nodeLayer.selectAll(".node") 
    .data(items, function(d) { return d.id; }) 

var nodeEnter = node.enter() 
    .append("g") 
    .attr("class", "node"); 

nodeEnter.append("circle") 
    .attr("r", 2.5) 
    .attr('class', 'circle') 
    .merge(node.select('circle')) 
    .attr('fill', 'red'); 

nodeEnter.append("text") // insert 
    .attr("dy", 3) 
    .text(function(d) { return d.name; }) 
    .merge(node.select('text')) 
    .attr('fill', 'green'); 

// You only need to call remove on the group, all the other exit().remove() calls are superfluous 
node.exit().remove(); 

simulation 
    .nodes(items); 

}

-1

var svg = d3.select("svg"), 
 
    width = +svg.attr("width"), 
 
    height = +svg.attr("height"), 
 
    nodeLayer = svg.append('g'), 
 
    node; 
 

 
var list = []; 
 
var links = []; 
 

 
var simulation = d3.forceSimulation(list) 
 
    .force("charge", d3.forceManyBody().strength(-1000)) 
 
    .force("link", d3.forceLink(links).distance(200)) 
 
    .force("center", d3.forceCenter(width/2, height/2)) 
 
    .on("tick", ticked); 
 

 
function createNodes(index) { 
 
    links.push({ 
 
    'source': 0, 
 
    'target': index 
 
    }) 
 
    list.push({ 
 
    "id": index, 
 
    "name": "server " + index 
 
    }); 
 
    return list; 
 
} 
 

 
var iteration = 0; 
 
update(createNodes(iteration)); // just simulating updates 
 

 
d3.interval(function(timer) { 
 
    iteration++; 
 
    update(createNodes(iteration)); 
 
}, 1000); //<-- this was commented out incorrectly just now 
 

 
function update(items) { 
 
    var dataJoin = nodeLayer.selectAll(".node") 
 
    .data(items, function(d) { 
 
     return d.id; 
 
    }); 
 
    node = dataJoin.enter() // insert 
 
    .append("g") 
 
    .attr("class", "node"); 
 

 
    node.append("circle") // insert 
 
    .attr("r", 2.5) 
 
    .attr('class', 'circle') 
 
    .merge(dataJoin) // not the class, the actual selected group you called enter() on 
 
    .select('.circle') 
 
    .style('fill', 'red') // just for testing purposes 
 
    .exit().remove(); // exit 
 

 
    node.append("text") // insert 
 
    .attr("dy", 3) 
 
    .attr('class', 'text') 
 
    .text(function(d) { 
 
     return d.name; 
 
    }) 
 
    .merge(dataJoin) 
 
    .select('.text') 
 
    .style('fill', 'green') // fill is a style 
 

 
    dataJoin.exit().remove(); 
 
    simulation.nodes(list); 
 
    simulation.force("link").links(links); 
 
    simulation.alpha(1).restart(); 
 
} 
 

 
function ticked() { 
 
    node.attr("transform", function(d) { 
 
    var a = d.x || 0; 
 
    var b = d.y || 0; 
 
    return "translate(" + a + ", " + b + ")"; 
 
    }); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.4.1/d3.min.js"></script> 
 
<svg height="300" width="300"></svg>

有一堆虫子,

首先 '更新' 的(用词不当)应该用所有数据节点的列表来调用,而不仅仅是改变。

你可能想探索https://bl.ocks.org/并复制人们如何做力的指导图。你需要链接才能拥有部队。

合并背后的想法是将新列表与旧列表进行比较,这意味着您需要使用dataJoin或具有数据/ ID的组。

我不是专家,看看所有的强制导向图的例子,看看他们如何更新/合并。 (有超过1种方式更新/重新启动图)

+0

对负面投票感到惊讶,因为我提供了演示合并语法的固定代码和工作代码。不倾向于更新,也建议你重拍这个问题,谢谢 – softwarenewbie7331

+0

我还没有投票给你 – Frame91

+0

也,你的例子不起作用。看到https://jsfiddle.net/cvvfsg97/7/,我用你的例子'文本',但约翰的方法'圆' – Frame91