d3.js尝试为数据设置动画,但更改的数据始终被视为新数据

时间:2014-05-16 00:25:34

标签: javascript json d3.js

我有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);

}

1 个答案:

答案 0 :(得分:1)

你非常接近。只需确保选择您创建的元素(.attr("class", "node");)。所以:

var nodes = svg.selectAll(".node")
    .data(graphFrame);

您在"node"上选择了不存在的内容,因此始终设置了输入选择。可以让数据绑定基于索引(默认值),因为您基本上是在选择中移动相同的项目(=相同的索引)。

这是一个完整的工作PLUNK