布局:layout
作用: 將不適合用于繪圖的數(shù)據(jù)轉(zhuǎn)換成了適合用于繪圖的數(shù)據(jù)。所以說愈魏,布局的作用可以解釋為:數(shù)據(jù)轉(zhuǎn)換。
今天選力導(dǎo)向圖(Force)和餅狀圖(Pie)作為例子。
力導(dǎo)向圖:
在二維或三維空間里配置節(jié)點寸宵,節(jié)點之間用線連接檩帐,稱為連線术幔。各連線的長度幾乎相等,且盡可能不相交湃密。節(jié)點和連線都被施加了力的作用诅挑,力是根據(jù)節(jié)點和連線的相對位置計算的四敞。根據(jù)力的作用,來計算節(jié)點和連線的運動軌跡拔妥,并不斷降低他們的能量忿危,最終達到一種能量很低的安定狀態(tài)。力導(dǎo)向圖能表示節(jié)點之間多對多的關(guān)系没龙。
現(xiàn)在我們拿到了這樣的一些初始數(shù)據(jù):
var nodes = [ { name: "計科" }, { name: "經(jīng)管" },
{ name: "法學(xué)" }, { name: "文藝" },
{ name: "理學(xué)" }, { name: "信息" },
{ name: "土建" } ];
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 } ];
這兩個數(shù)組分別是表示節(jié)點和連線铺厨。
要作圖,我們首先需要在頁面中定義一塊svg畫布硬纤。
// 定義一下svg的寬和高努释。
var height = 1000;
var width = 1000;
var svg = d3.select("body").append("svg").attr("width",width).attr("height",height); // 添加一塊svg畫布
接下來需要一個力導(dǎo)向圖的布局:
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.size([width,height])
.linkDistance(150)
.charge([400]);
force.start()// 開始作用
上面的代碼中 nodes:指定節(jié)點數(shù)組 links :指定連線數(shù)組 size : 指定作用范圍 linkDistance:指定連線長度 charge: 相互之間的作用力
轉(zhuǎn)換后,節(jié)點對象里多了一些變量咬摇。其意義如下:
index - 節(jié)點的索引號
px, py - 節(jié)點上一個時刻的坐標
x, y - 節(jié)點的當前坐標
weight - 節(jié)點的權(quán)重
接下來伐蒂,繪制的圖形元素有:
- line 線段,連線
- cilcle 圓肛鹏,表示節(jié)點
- text 文字逸邦,描述節(jié)點
//添加連線
var svg_edges = svg.selectAll("line")
.data(edges)
.enter()
.append("line")
.style("stroke","#ccc") //線的顏色
.style("stroke-width",1); // 線的寬度
var color = d3.scale.category20(); //產(chǎn)生隨機顏色
//添加節(jié)點
var svg_nodes = svg.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("r",20) // 圓的半徑
.style("fill",function(d,i){
return color(i); // 填充圓的顏色
})
.call(force.drag); //使得節(jié)點能夠拖動
//添加描述節(jié)點的文字
var svg_texts = svg.selectAll("text")
.data(nodes)
.enter()
.append("text")
.style("fill", "black")
.attr("dx", 20)
.attr("dy", 8) // 如果不要這兩行,字會出現(xiàn)在節(jié)點的右上角
.text(function(d){
return d.name;
});
最后在扰,在監(jiān)聽器里完成刷新:
force.on("tick", function(){ //對于每一個時間間隔
//更新連線坐標
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; });
//更新節(jié)點坐標
svg_nodes.attr("cx",function(d){ return d.x; })
.attr("cy",function(d){ return d.y; });
//更新文字坐標
svg_texts.attr("x", function(d){ return d.x; })
.attr("y", function(d){ return d.y; });
});
下面是餅狀圖的代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>一個餅狀圖</title>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js" charset="UTF-8"></script>>
<script>
var dataset = [40,23,15,34,55,23];
var dataset2 = ["土建","法學(xué)","經(jīng)管","計科","制造","文藝"];
var width = 1000;
var height = 1000;
var svg = d3.select("body")
.append("svg")
.attr("width",width)
.attr("height",height);
var color = d3.scale.category20();
var pie = d3.layout.pie() //創(chuàng)建一個pie布局缕减,他擁有處理數(shù)據(jù)的能力
var piedata = pie(dataset); // 把數(shù)據(jù)交給pie來處理,結(jié)果保存在piedata中
var outR = 300; //設(shè)置餅狀圖的內(nèi)徑
var innerR = 100; // 外徑
//現(xiàn)在我們需要一個弧生成器
var arc = d3.svg.arc()
.innerRadius(innerR)
.outerRadius(outR);
//svg中添加幾個g元素芒珠,每個用于放一段弧
var arcs =svg.selectAll("g")
.data(piedata)
.enter()
.append("g")
.attr("transform","translate("+(width/2)+","+(width/2)+")");
//平移桥狡,這里是指向右和向下各平移width/2;
//給每個g添加一個path
arcs.append("path")
.attr("fill",function(d,i){
return color(i);
})
.attr("d",function(d,i){
return arc(d); arc(d)的d是被綁定的數(shù)據(jù),arc(d)返回值賦給路徑的d屬性
});
arcs.append("text")
.attr("transform",function(d){
return "translate("+arc.centroid(d)+")" // 弧線中心
})
.attr("text-anchor","middle") //居中
.text(function(d,i){
return dataset2[i]; // 這里將要添加的文本放入便可以了
})
</script>
</body>
</html>