如何通过d3.js绘制多边形

时间:2017-02-15 13:12:20

标签: javascript d3.js

我使用d3.js创建了五个节点,并且相互建立链接以制作多边形,但它们不是相邻的位置来制作多边形,而是制作除了多边形之外的随机视图。我在这里遗漏了一些东西,请看一下并建议我。



 var width = 300,
   height = 300

 var svg = d3.select("body").append("svg")
   .attr("width", width)
   .attr("height", height);


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


 var datajson = {
   "nodes": [{
     "name": "a",
     "group": 2
   }, {
     "name": "b",
     "group": 1
   }, {
     "name": "c",
     "group": 1
   }, {
     "name": "d",
     "group": 2
   }, {
     "name": "e",
     "group": 2
   }],
   "links": [{
     "source": 0,
     "target": 1,
     "value": 1,
     "distance": 90
   }, {
     "source": 1,
     "target": 2,
     "value": 2,
     "distance": 90
   }, {
     "source": 2,
     "target": 3,
     "value": 3,
     "distance": 90
   }, {
     "source": 3,
     "target": 4,
     "value": 5,
     "distance": 90
   }, {
     "source": 4,
     "target": 0,
     "value": 5,
     "distance": 90
   }]
 }


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


 var drag = force.drag()
   .on("dragstart", dblclick);


 var link = svg.selectAll(".link")
   .data(datajson.links)
   .enter().append("line")
   .attr("class", "link");

 var node = svg.selectAll(".node")
   .data(datajson.nodes)
   .enter().append("g")
   .attr("class", "node")
   .call(force.drag);

 node.append("image")
   .attr("x", -8)
   .attr("y", -8)
   .attr("width", 45)
   .attr("height", 45)
   .attr("xlink:href", function(d) {
     var rnd = Math.floor(Math.random() * 64 + 1);


     return null;
   });

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

 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("transform", function(d) {
     return "translate(" + d.x + "," + d.y + ")";
   });
 });

 function dblclick(d) {


   d3.select(this).classed("fixed", d.px = d.x, d.py = d.y);
   console.log(d);
 }

.link {
  stroke: #dfdfdf;
}
.node text {
  pointer-events: none;
  font: 10px sans-serif;
}
.link.red {
  stroke: blue;
}

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

<body>
  <script src="http://d3js.org/d3.v3.min.js"></script>
</body>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

致电时

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

d3随机选择节点的起始位置,因为它们尚未分配xy属性。

但是,在调用上面的代码之前,您可以遍历每个节点并为其分配多边形角的xy,并且它们应该保持这种关系。虽然他们可能不会反弹很多,因为他们已经处于预期的位置。在这种情况下,您可以通过在起始值中添加一些随机的x和y位移,稍微改变它们相对于最终预期位置的位置。

工作示例

预定位节点的代码是

 var numNodes = datajson.nodes.length
 var r = 20;
 datajson.nodes.forEach(function(node, i) {
   node.x = width/2  + r * Math.sin(2 * Math.PI * i / numNodes)
   node.y = height/2 + r * Math.cos(2 * Math.PI * i / numNodes)
   console.log(node)
 })

我还必须调整电荷(-1000)和linkDistance(100)以使其工作。

&#13;
&#13;
 var width = 300,
   height = 300

 var svg = d3.select("body").append("svg")
   .attr("width", width)
   .attr("height", height);


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


 var datajson = {
   "nodes": [{
     "name": "a",
     "group": 2
   }, {
     "name": "b",
     "group": 1
   }, {
     "name": "c",
     "group": 1
   }, {
     "name": "d",
     "group": 2
   }, {
     "name": "e",
     "group": 2
   }],
   "links": [{
     "source": 0,
     "target": 1,
     "value": 1,
     "distance": 90
   }, {
     "source": 1,
     "target": 2,
     "value": 2,
     "distance": 90
   }, {
     "source": 2,
     "target": 3,
     "value": 3,
     "distance": 90
   }, {
     "source": 3,
     "target": 4,
     "value": 5,
     "distance": 90
   }, {
     "source": 4,
     "target": 0,
     "value": 5,
     "distance": 90
   }]
 }

 var numNodes = datajson.nodes.length
 var r = 20;
 datajson.nodes.forEach(function(node, i) {
   node.x = width/2  + r * Math.sin(2 * Math.PI * i / numNodes)
   node.y = height/2 + r * Math.cos(2 * Math.PI * i / numNodes)
   console.log(node)
 })

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


 var drag = force.drag()
   .on("dragstart", dblclick);


 var link = svg.selectAll(".link")
   .data(datajson.links)
   .enter().append("line")
   .attr("class", "link");

 var node = svg.selectAll(".node")
   .data(datajson.nodes)
   .enter().append("g")
   .attr("class", "node")
   .call(force.drag);

 node.append("image")
   .attr("x", -8)
   .attr("y", -8)
   .attr("width", 45)
   .attr("height", 45)
   .attr("xlink:href", function(d) {
     var rnd = Math.floor(Math.random() * 64 + 1);


     return null;
   });

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

 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("transform", function(d) {
     return "translate(" + d.x + "," + d.y + ")";
   });
 });

 function dblclick(d) {


   d3.select(this).classed("fixed", d.px = d.x, d.py = d.y);
   console.log(d);
 }
&#13;
.link {
  stroke: #dfdfdf;
}
.node text {
  pointer-events: none;
  font: 10px sans-serif;
}
.link.red {
  stroke: blue;
}
&#13;
<!DOCTYPE html>
<meta charset="utf-8">

<body>
  <script src="http://d3js.org/d3.v3.min.js"></script>
</body>
&#13;
&#13;
&#13;