如何在d3 v4中绘制力图?

时间:2016-12-07 09:36:32

标签: javascript d3.js

我是d3的新手,当我学习如何绘制力图时,我遇到了一些问题。首先,让我们在这里看到我的代码:

<html>
<head>
<meta charset="UTF-8">
<title>the force chart</title>
</head>
 
<body>
    <script src="http://d3js.org/d3.v4.min.js"></script>
    <script> 
        var width = 400;        
        var height = 400;    
        var svg = d3.select("body")    
                    .append("svg")     
                    .attr("width",width)      
                    .attr("height",height);     
        var nodes = [ { "id": "English" },{ "id": "Italy" },
                      { "id": "America" },{ "id": "Canada" },
                      { "id": "Australia" },{ "id": "Japan" },
                      { "id": "China" } ];
        var edges = [ { "source": 0 , "target": 1 } , { "source": 0 , "target": 2 },
                      { "source": 0 , "target": 3 } , { "source": 1 , "target": 4 },
                      { "source": 1 , "target": 5 } , { "source": 1 , "target": 6 }, ];


        var force = d3.forceSimulation(nodes)  
                    .force("link",d3.forceLink()
                    .id(function(d){return d.id})
                    .distance(function(d){return 150}).strength([-400]))
                    .force("charge",d3.forceManyBody())
                    .force("center",d3.forceCenter(width , height));

            force.restart(); //start

        var svg_edges = svg.selectAll("line")
            .data(edges)
            .enter()
            .append("line")
            .style("stroke","#ccc")
            .style("stroke-width",1);

        var color = d3.scaleOrdinal(d3.schemeCategory20);

        //add nodes
        var svg_nodes = svg.selectAll("circle")
            .data(nodes)
            .enter()
            .append("r",20)
            .style("fill",function(d,i){
                return color(i);
            })
            .call(d3.drag());   //to drag the nodes

        //add information
        var svg_texts = svg.selectAll("text")
            .data(nodes)
            .enter()
            .append("text")
            .style("fill", "black")
            .attr("dx", 20)
            .attr("dy", 8)
            .text(function(d){
                return d.id;
            });

        force.on("tick", function(){ //update the position of lines
            svg_edges.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; })

            //update the position of nodes
            svg_nodes.attr("cx",function(d){ return d.x; })
                .attr("cy",function(d){ return d.y; });

            //update the position of information
            svg_texts.attr("x",function(d){ return d.x; })
                .attr("y",function(d){ return d.y; });

        });
    </script>     
</body>
</html>

我想画一幅这样的照片: enter image description here

但我的代码只能显示一个节点,就像这样:

enter image description here

所以我感到困惑,因为开发者工具中没有错误。当我布置力量时,我推断https://github.com/d3/d3-force/blob/master/README.md#links。所以我解决了不同版本产生的问题。但为什么它仍然不起作用?你可以帮帮我吗?如果你帮助我,我非常感激!谢谢!

2 个答案:

答案 0 :(得分:2)

除了已经由@Vinod解释的要点:

.append("circle")

.force("center", d3.forceCenter(width/2, height/2));

你有一个尾随逗号。但最重要的是这一点,以显示边缘:

首先,将边添加到模拟中:

force.force("link")
    .links(edges);

然后,更改链接ID。目前,没有名为id的财产。所以,它应该是:

.force("link", d3.forceLink()
    .id(function(d,i) {
        return i
    })
    //the rest of the function

这是一个演示:

&#13;
&#13;
 var width = 400;
 var height = 400;
 var svg = d3.select("body")
     .append("svg")
     .attr("width", width)
     .attr("height", height);
 var nodes = [{
     "id": "English"
 }, {
     "id": "Italy"
 }, {
     "id": "America"
 }, {
     "id": "Canada"
 }, {
     "id": "Australia"
 }, {
     "id": "Japan"
 }, {
     "id": "China"
 }];
 var edges = [{
     "source": 0,
     "target": 1
 }, {
     "source": 0,
     "target": 2
 }, {
     "source": 0,
     "target": 3
 }, {
     "source": 1,
     "target": 4
 }, {
     "source": 1,
     "target": 5
 }, {
     "source": 1,
     "target": 6
 }];


 var force = d3.forceSimulation()
     .force("link", d3.forceLink()
         .id(function(d,i) {
             return i
         })
         .distance(function(d) {
             return 150
         }))
     .force("charge", d3.forceManyBody())
     .force("center", d3.forceCenter(width/2, height/2));

 force.restart(); //start

 var svg_edges = svg.selectAll("line")
     .data(edges)
     .enter()
     .append("line")
     .style("stroke", "#ccc")
     .style("stroke-width", 1);

 var color = d3.scaleOrdinal(d3.schemeCategory20);

 //add nodes
 var svg_nodes = svg.selectAll("circle")
     .data(nodes)
     .enter()
     .append("circle")
		 .attr("r", 20)
     .style("fill", function(d, i) {
         return color(i);
     })
     .call(d3.drag()); //to drag the nodes

 //add information
 var svg_texts = svg.selectAll("text")
     .data(nodes)
     .enter()
     .append("text")
     .style("fill", "black")
     .attr("dx", 20)
     .attr("dy", 8)
     .text(function(d) {
         return d.id;
     });
		 
	force.nodes(nodes);
	force.force("link")
      .links(edges);

 force.on("tick", function() { //update the position of lines
     svg_edges.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;
         })

     //update the position of nodes
     svg_nodes.attr("cx", function(d) {
             return d.x;
         })
         .attr("cy", function(d) {
             return d.y;
         });

     //update the position of information
     svg_texts.attr("x", function(d) {
             return d.x;
         })
         .attr("y", function(d) {
             return d.y;
         });

 });
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

您的代码中存在多个错误

首先你需要像这样追加圈子

  var svg_nodes = svg.selectAll("circle")

        .data(nodes)
        .enter()
        .append("circle")
        .attr("r",20)
        .style("fill",function(d,i){
            return color(i);
        })
        .call(d3.drag());   //to drag the nodes

当你的代码附加r而不是SVG标签时,图形的中心不应该是宽度和高度,它应该是宽度/ 2和高度/ 2以使其处于中心

请参阅此小提琴http://jsfiddle.net/Qh9X5/9515/

类似地,对于使用边缘数据的线条,如果没有x,y值,则需要为绘制线传递xy值

有关v3.3中的完整解决方案说明,请参阅此https://jsfiddle.net/3uehrfj8/1/以及所有节点和边