2017-01-13 47 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