D3 延迟添加 link

D3 add link with delay

我想为下面的 D3 图添加一些功能,这样每个 link 及其对应的节点都会在延迟 1 秒后添加(即一次添加一个)。有什么办法吗?

数据来自加载一次的外部 JSON 文件(此处未显示)。这里,我们假设JSON文件不会随时间变化,所以我们在开始时解析一次JSON文件就够了。

      <!DOCTYPE html>
            <meta charset="utf-8">
            <style>

            .link {
              stroke: #ccc;
            }

            .node text {
              pointer-events: none;
              font: 10px sans-serif;
            }

            </style>
            <body>

            <script src="http://d3js.org/d3.v3.min.js"></script>
            <script>

            //Constants for the SVG
            var width = 2480,
                height = 2880;

            //Set up the colour scale
            var color = d3.scale.category10();

            //Set up the force layout


            var force = d3.layout.force()
                .charge(-100)
                .linkDistance(300)
                .size([width, height]);

            //Append a SVG to the body of the html page. Assign this SVG as an object to svg
            var svg = d3.select("body").append("svg")
                .attr("width", width)
                .attr("height", height);

            //Read the data from the mis element 
            d3.json("data.json", function(error, graph) {
              force
                  .nodes(graph.nodes)
                  .links(graph.links)
                  .start();



            //Create all the line svgs but without locations yet
            var link = svg.selectAll(".link")
                .data(graph.links)
                .enter().append("line")
                .attr("class", "link")
                .style("stroke-width", function (d) {
                return Math.sqrt(d.value);
            });

            //Do the same with the circles for the nodes - no 
            //Changed
            var node = svg.selectAll(".node")
                .data(graph.nodes)
                .enter().append("g")
                .attr("class", "node")
                .call(force.drag);

            node.append("circle")
                .attr("r", 8)
                .style("fill", function (d) {
                return color(d.group);
            })

            node.append("text")
                  .attr("dx", 10)
                  .attr("dy", ".35em")
                  .text(function(d) { return d.name });
            //End changed


            //Now we are giving the SVGs co-ordinates - the force layout is generating the co-ordinates which this code is using to update the attributes of the SVG elements
            force.on("tick", function () {
                link.attr("x1", function (d) {
                    return d.source.x;
                })
                    .attr("y1", function (d) {
                    return d.source.y;
                })
                    .attr("x2", function (d) {
                    return d.target.x;
                })
                    .attr("y2", function (d) {
                    return d.target.y;
                });

                //Changed

                d3.selectAll("circle").attr("cx", function (d) {
                    return d.x;
                })
                    .attr("cy", function (d) {
                    return d.y;
                });

                d3.selectAll("text").attr("x", function (d) {
                    return d.x;
                })
                    .attr("y", function (d) {
                    return d.y;
                });

                //End Changed

            });

            });

            </script>

使用setTimeOut方法。

graph.links.forEach(function(d, i) {
    setTimeout(function() {
        var nodes = graph.nodes.filter(function(n,i){
            return d.source.index==i || d.target.index==i
        });
        nodes.forEach(function(node){
            var nodeG = container.append("g")
                .datum(node)
                .attr("class", "node")
                .attr("cx", function(d) {
                    return d.x;
                })
                .attr("cy", function(d) {
                    return d.y;
                })
                .call(drag);
            nodeG.append("circle")
                .attr("r", function(d) {
                    return d.weight * 2 + 12;
                })
                .style("fill", function(d) {
                    return color(1 / d.rating);
                });
        });
        container.append("line")
            .datum(d)
            .attr("class", "link")
            .style("stroke-width", function(d) {
                return Math.sqrt(d.value);
            });   
       force.resume();  //Restarts the force simulation.  
    }, 1000 * i);
});

另外不要忘记更新刻度函数,如下所示。

force.on("tick", function() {
     container.selectAll(".link")
              .attr("x1", function(d) { return d.source.x; })
              .attr("y1", function(d) { return d.source.y; })
              .attr("x2", function(d) { return d.target.x; })
              .attr("y2", function(d) { return d.target.y; });

     container.selectAll(".node")
              .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
});

Working JSFiddle