I have json data: an array of frames, each frame is an array of 10 nodes, and each node is a dictionary with the node id and x,y coordinates. I want to create a d3 animation that transitions between the positions of the node in each frame.
I am using setInterval(...) to set up the transitions to the next set of node positions. However, a bunch of new nodes are added instead of the existing nodes updating by going through the transition. Am I doing something wrong with the key function, or something else?
Here's a sample of what the json looks like:
[[{"y": "0.898287995669", "x": "0.824201870934", "v": "0"}, {"y": "0.738482578278", "x": "0.645352934631", "v": "1"}, {"y": "0.12255740116", "x": "0.113578656145", "v": "2"}, {"y": "0.603047665154", "x": "0.609252770235", "v": "3"}, {"y": "0.497780597993", "x": "0.490370637301", "v": "4"}, {"y": "0.450309984776", "x": "0.428403273731", "v": "5"}, {"y": "0.512235180495", "x": "0.552584811488", "v": "6"}, {"y": "0.808721117001", "x": "0.829379563316", "v": "7"}, {"y": "0.771161177414", "x": "0.378854605349", "v": "8"}, {"y": "0.48703522369", "x": "0.162086851046", "v": "9"}], [{"y": "0.848393476015", "x": "0.0502693724025", "v": "0"}, {"y": "0.220251557696", "x": "0.653522019136", "v": "1"}, {"y": "0.0885518976544", "x": "0.17830262921", "v": "2"}, {"y": "0.179368661434", "x": "0.597837803239", "v": "3"}, {"y": "0.0333228956342", "x": "0.985417214534", "v": "4"}, {"y": "0.502384226146", "x": "0.668414759643", "v": "5"}, {"y": "0.242769234767", "x": "0.827774288391", "v": "6"}, {"y": "0.227109062114", "x": "0.352454692633", "v": "7"}, {"y": "0.830790971204", "x": "0.57313727618", "v": "8"}, {"y": "0.854927945281", "x": "0.0879122992914", "v": "9"}], ... ]
and here's what my current code is:
var width = 960,
height = 500;
var padding = 10;
// inverted because of svg inverted y axis
var yscale = d3.scale.linear().domain([1,0]).range([padding, height - padding]);
var xscale = d3.scale.linear().domain([0,1]).range([padding, width - padding]);
var color = d3.scale.category20();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("out.json", function(error, json) {
if (error) return console.warn(error);
var graphFrames = json;
startDrawing(graphFrames);
});
function drawFrame(graphFrame) {
// DATA JOIN
// Join new data with old elements, if any.
var nodes = svg.selectAll("node")
.data(graphFrame, function(d){ return d.v; });
// UPDATE
// Update old elements as needed.
nodes.transition()
.duration(750)
.attr("cx", function(d) { return xscale(d.x); })
.attr("cy", function(d) { return yscale(d.y); });
// ENTER
// Create new elements as needed.
nodes.enter().append("circle")
.attr("class", "node")
.attr("r", 5)
.attr("cx", function(d) { return xscale(d.x); })
.attr("cy", function(d) { return yscale(d.y); })
.style("fill", function(d, i){ return color(d.v % 20); });
// EXIT
// Remove old elements as needed.
//nodes.exit().remove();
}
var nextFrameIdx = 1;
function startDrawing(graphFrames){
// The initial display.
drawFrame(graphFrames[0]);
// Draw the next set of node coordinates at each interval
setInterval(function() {
drawFrame(graphFrames[nextFrameIdx]);
nextFrameIdx = (nextFrameIdx + 1) % graphFrames.length;
}, 1500);
}