13장 풀이 13.2.1

<예제 13.2.1 풀이>

SVG 캔버스는 다음과 같이 지정한다.

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

D3의 force 레이아웃은 다음 예와 같이 지정한다. 이 예는 최소한의 속성을 지정한 것으로 dataSet의 nodes와 links를 지정해주고, size()로 force 레이아웃의 크기를 지정하며, gravity()로 중심에서 당기는 힘을 지정하며, distance()로 엣지의 길이를 지정하고, charge()로 노드끼리 밀어내는 힘(음수 일 경우 밀어내는 힘이 강함)을 지정하여 노드끼리 멀리 떨어지도록 조정한다.

var force = d3.layout.force()
.nodes(dataSet.nodes)
.links(dataSet.links)
.size([width, height])
.gravity(.05)
.distance([100])
.charge([-100])
.start();

엣지의 선 지정은 다음과 같다. 선의 굵기를 데이터의 weight를 이용하였다.

var link = svg.selectAll("line")
.data(dataSet.links)
.enter()
.append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return d.weight); });

노드을 위한 원 요소의 지정은 다음과 같다. 마지막 줄의 .call(force.drag)은 드랙-드롭(drag and drop)을 위한 명령어이다.

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

마지막으로 force layout의 틱(tick)을 다음과 같이 지정한다. 이 틱은 축 설정에서의 틱과는 다른 의미로서 네트워크 그래프가 움직이듯이 보이게 하는 시뮬레이션을 뜻한다. 이때 사용되는 x, y좌표는 D3가 계산한 노드 원의 중심 좌표와 링크 선의 좌표이다.

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

다음과 같은 EX130201.htm 파일을 만든 후 크롬으로 실행하면 <그림 13.2.1>과 같다.

<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v2.min.js"></script>
<style>
  .node{stroke:none; stroke-width:3px; fill:indianred;}
  .link{stroke: black;}
  .text{font-family: sans-serif; fill: black; font-size: 10pt; }
</style>
<body>
<h3> 네트워크 그래프 </h3>
<script>
// SVG 캔버스
var width  = 300, height = 300;
var svg = d3.select("body").append("svg").attr("width",  width).attr("height", height);
// 데이터
var dataSet = {
  "nodes":[
{"name":"node1","group":1},
{"name":"node2","group":2},
{"name":"node3","group":2},
{"name":"node4","group":3},
{"name":"node5","group":3}
  ],
  "links":[
{"source":0,"target":2,"weight":1},
{"source":1,"target":2,"weight":2},
{"source":2,"target":1,"weight":1},
{"source":2,"target":4,"weight":3},
{"source":3,"target":4,"weight":3}
  ]
}
// force 레이아웃
var force = d3.layout.force()
    .nodes(dataSet.nodes)
    .links(dataSet.links)
    .size([width, height])
    .gravity(.05)
    .distance([100])
    .charge([-100])
    .start();
// 엣지 
var link = svg.selectAll("line")
    .data(dataSet.links).enter().append("line").attr("class", "link")
    .style("stroke-width", function(d) { return Math.sqrt(d.weight); });
// 노드
var node = svg.selectAll("circle")
    .data(dataSet.nodes).enter().append("g").attr("class", "node")
    .call(force.drag);
node.append("circle").attr("r","10");
node.append("text").attr("class","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 + ")"; } );
});
</script>
</body>
</html>

<그림 13.2.1> 간단한 네트워크 그래프 예

Leave a Reply

Your email address will not be published. Required fields are marked *