简体   繁体   English

使用D3逐个节点构建图形节点

[英]Building a graph node by node with D3

I have a graph structure that stored in json format that looks like this: 我有一个以json格式存储的图形结构,如下所示:

{
    "links": [
        {
            "source": 1, 
            "target": 0, 
            "value": 1
        }, 
        {
            "source": 2, 
            "target": 0, 
            "value": 1
        }, 
        {
            "source": 3, 
            "target": 0, 
            "value": 1
        }
    ],
    "nodes": [
            {
                "group": 3, 
                "name": "justintimberlake"
            }, 
            {
                "group": 2, 
                "name": "Anastacia Lyn Newton"
            }, 


     {
            "group": 2, 
            "name": "Maria Do Carmo"
        }
],
"time": [
        {
            "source": 1, 
            "time": 6.854456018518518
        }, 
        {
            "source": 2, 
            "time": 6.320115740740741
        }, 
        {
            "source": 3, 
            "time": 5.962986111111111
        }
]
}

And I have D3 code that draws this network: 我有绘制此网络的D3代码:

<!DOCTYPE html xmlns:xlink="http://www.w3.org/1999/xlink">
<meta charset="utf-8">
<style>
// style here
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="animviz"></div>
<script>

    d3.json("post000.json", function(error, graph) {

        var vv = window,
            w = vv.innerWidth,
            h = vv.innerHeight;

        var svg = d3.select("#animviz")
                .append("svg")
                .attr("width", w)
                .attr("height", h)
                .append("g")
                .call(d3.behavior.zoom().scaleExtent([0, 8]).on("zoom", zoom))
                .append("g");

        var color = d3.scale.category10();

        var force = d3.layout.force()
                .charge(-200)
                .linkDistance(50)
                .size([w, h]);

        force
                .nodes(graph.nodes)
                .links(graph.links)
                .start();

        var link = svg.selectAll(".link")
                .data(graph.links)
                .enter().append("line")
                .attr("class", "link")
                .attr("transform", function(d) { return "translate(" + d + ")"; });

        function zoom() {
          svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }

        var myMouseoverFunction = function() {
            var circle = d3.select(this);
            circle.transition().duration(100)
                    .attr("r", 20 )
            node.append("title")
                .text(function(d) { return d.name});
        }

        var myMouseoutFunction = function() {
            var circle = d3.select(this);
            circle.transition().duration(500)
                    .attr("r", 10 );
        }
        var node = svg.selectAll(".node")
                .data(graph.nodes)
                .enter().append("circle")
                .attr("class", "node")
                .attr("r", 10)
                .style("fill", function(d) { return color(d.group); })
                .call(force.drag)
                .on("mouseover", myMouseoverFunction)
                .on("mouseout", myMouseoutFunction);


        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; });

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

    });


</script>

</body>

What I want is to draw this graph node by node according to time parameter (ie source: 1 should be drawn after 6.854456018518518 sec after node = 0 was drawn). 我想要的是根据时间参数逐个节点绘制此图(即源:应在绘制节点= 0后的6.854456018518518秒后绘制1)。

If it's not possible to draw them after special number of seconds, I'd like at least to draw them in order, so that I can see how nodes appear one after the other. 如果无法在特定的秒数后绘制它们,我至少希望按顺序绘制它们,以便可以看到节点如何一个接一个地显示。

I checked similar questions ( here , here , and here ) and this tutorial but wasn't able to solve my problem. 我检查了类似的问题( 此处此处此处 )和本教程,但无法解决我的问题。 Ideally I would love to have similar to this but for my data from json file and not in infinite loop. 理想我很想有类似这个 ,但是从JSON文件我的数据,而不是在无限循环。

How can I draw a graph stored in json node by node? 如何按节点绘制存储在json节点中的图形?

one way to achieve this is to create nodes with radius = 0 , and then use delay for showing each node (giving it radius = 12 ): 实现此目的的一种方法是创建radius = 0节点,然后使用delay来显示每个节点(给定radius = 12 ):

node.attr("r", 0);

var totalDelay = 0;  
    node
      .transition()
      .duration(0)
      .delay(function(d, i) {
        totalDelay += graph.time[i].time * 1000;
        return totalDelay
      })
      .attr("r", 12);

See this jsFiddle 看到这个jsFiddle

The problem with this solution is that all the links appear immediately, without waiting for its nodes to appear. 该解决方案的问题在于,所有链接都立即显示,而无需等待其节点出现。

Added: to deal with links problem, you may want to redraw graph after each interval, every time adding one node, and calculating the array of links for the nodes, displayed in each iteration: 补充:为解决链接问题,您可能希望在每个间隔之后重绘图形,每次添加一个节点,并计算节点的链接数组,这些数组在每次迭代中显示:

var i = 0;
function redraw() {
    if (i === graph.time.length) return;
    setTimeout(function() {
        var nodes = graph.nodes.slice(0, i + 1);
        var links = graph.links.filter(function(link) {
            return (link.source <= i && link.target <= i) 
        });

        draw(nodes, links);
        i += 1;

        redraw();    
    }, graph.time[i].time * 1000);
}

See improved jsFiddle 查看改进的jsFiddle

For big datasets might be more efficient to keep the same nodes array and do nodes.push(graph.nodes[i]) , instead of creating a new array in each iteration. 对于大型数据集,保持相同的nodes数组并执行nodes.push(graph.nodes[i])可能会更有效,而不是在每次迭代中创建一个新的数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM