我有json数据:一个帧数组,每个帧是一个包含10个节点的数组,每个节点都是一个带有节点id和x,y坐标的字典。 我想创建一个d3动画,在每个帧的节点位置之间转换。
我正在使用setInterval(...)来设置到下一组节点位置的转换。但是,通过转换添加了一堆新节点而不是现有节点更新。 我是否在使用键功能或其他方面做错了什么?
以下是json的样子:
[[{"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"}], ... ]
以及我目前的代码是什么:
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);
}
答案 0 :(得分:1)
你非常接近。只需确保选择您创建的元素(.attr("class", "node");
)。所以:
var nodes = svg.selectAll(".node")
.data(graphFrame);
您在"node"
上选择了不存在的内容,因此始终设置了输入选择。可以让数据绑定基于索引(默认值),因为您基本上是在选择中移动相同的项目(=相同的索引)。
这是一个完整的工作PLUNK。