I'm trying to dynamically update a d3 circle pack layout with data I receive in json. Every second I call d3.json() to get the new json. Instead of updating the existing visualization, my implementation just creates a new one under the old one. I want to to dynamically update the existing layout instead...
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="d3.v2.js">
</script>
<script type="text/javascript" src="jquery-1.4.min.js"></script>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="stylesheet" href="syntax.css" type="text/css">
<link rel="stylesheet" href="pack.css" type="text/css">
</head>
<body>
<div id="chart"> </div>
<script type="text/javascript">
var width = 960,
height = 960,
format = d3.format(",d");
var pack = d3.layout.pack()
.size([width - 4, height -4])
.value(function(d) { return d.size; });
var vis = null;
var node = null;
vis = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "pack");
/* vis.append("g")
.attr("transform", "translate(2, 2)"); */
function update(json){
// Creating the circle packed core
var gNodes = vis.data([json]).selectAll("g.node")
.data(pack.nodes);
//remove old data
gNodes.exit().remove();
}
setInterval(function(){
d3.json("http://10.0.1.4:8080/cluster", function(json) {
update(json);
//update the visualization
vis
.selectAll("circle")
.data([json]).selectAll("g.node")
.data(pack.nodes)
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.transition()
.duration(500)
.attr("r", function(d) { return d.children ? coreSize : d.r; });
var node = gNodes
.enter().append("g")
.attr("class", function(d) { return d.children ? "node" : "leaf node"; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("title")
.text(function(d) { return (d==null? "": d.name + (d.children ? "" : ": " + format(d.size))); });
node.append("circle")
.attr("r", function(d) { return (d==null? 0: d.r); });
node.filter(function(d) { return (d==null? "" : !d.children); }).append("text")
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.text(function(d) { return (d==null?"":d.name.substring(0, d.r / 3)); });
});
}, 1000);
</script>
Take a look at my example here.
Basically, there is code for initial load, where all circles, tooltips, etc. are created and positioned in initial places. As well, the layout (pack) is created.
Than, on each button press, new data is loaded into pack, and the pack is recalculated. That crucial code is here:
if (dataSource == 0)
pack.value(function(d) { return d.size; });
if (dataSource == 1)
pack.value(function(d) { return 100; });
if (dataSource == 2)
pack.value(function(d) { return 1 +
Math.floor(Math.random()*501); });
var data1 = pack.nodes(data);
( I have three buttons, thats why 3 ifs)
After that, elements are tranistioned to new positions, and its attributes are changed as you determine.
Here are some pics with transition in action:
Start:
Transition:
End:
来源:https://stackoverflow.com/questions/11801674/updating-d3-circle-pack-layout