(本文章代码来自网络与《D3API详解》这本书,收集做学习交流之用)
1、捆绑布局
1.1、简介:
捆绑布局根据结点数据输入确定结点的父子关系,再根据边数据输入确定结点之间的边怎么画,当从一个结点映射出去的连接比较多时看上去像是形成一捆绳,所以叫捆图。适合展示如demo所示各大城市之间高铁连接关系这样的情况。
1.2、demo:
多个城市之间的高铁连接情况:
1.3、代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>捆图</title>
<style>
body{
background-color: #000000;
}
.node circle {
stroke: black;
stroke-width: 2px;
}
.node text{
font-size: 12px;
font-family: simsun;
}
.link {
fill: none;
stroke: white;
stroke-opacity: .5;
stroke-width: 8px;
}
</style>
</head>
<body>
<script src="../../d3.js"></script>
<script>
var width = 1370; //SVG绘制区域的宽度
var height = 670; //SVG绘制区域的高度
var svg = d3.select("body") //选择<body>
.append("svg") //在<body>中添加<svg>
.attr("width", width) //设定<svg>的宽度属性
.attr("height", height);//设定<svg>的高度属性
//1. 确定初始数据
var vertex = {
name: "",
children:[
{name: "北京"},{name: "上海"},{name: "杭州"},
{name: "广州"},{name: "桂林"},{name: "昆明"},
{name: "成都"},{name: "西安"},{name: "太原"}
]
};
var edges = [
{source: "北京", target: "上海"},
{source: "北京", target: "广州"},
{source: "北京", target: "杭州"},
{source: "北京", target: "西安"},
{source: "北京", target: "成都"},
{source: "北京", target: "太原"},
{source: "北京", target: "桂林"},
{source: "北京", target: "昆明"},
{source: "北京", target: "成都"},
{source: "上海", target: "杭州"},
{source: "昆明", target: "成都"},
{source: "西安", target: "太原"}
];
var Zoom_data = 400;//这个值可以调节图的大小
//2. 转换数据
var cluster = d3.layout.cluster()
.size([360, width/2 - Zoom_data])
.separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
var bundle = d3.layout.bundle();
//数据接口
var nodes = cluster.nodes(vertex);
var oLinks = map(nodes, edges);
var links = bundle(oLinks);
//将links中的source和target由名称替换成节点
function map( nodes, links ){
var hash = [];
for(var i = 0; i < nodes.length; i++){
hash[nodes[i].name] = nodes[i];
}
var resultLinks = [];
for(var j = 0; j < links.length; j++){
resultLinks.push({ source: hash[ links[j].source ],
target: hash[ links[j].target ]
});
}
return resultLinks;
}
//3. 绘图
var line = d3.svg.line.radial()
.interpolate("bundle")
.tension(.85)
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
gBundle = svg.append("g")
.attr("transform", "translate(" + (width/2) + "," + (height/2) + ")");
var color = d3.scale.category20c();
var link = gBundle.selectAll(".link")
.data(links)
.enter()
.append("path")
.attr("class", "link")
.attr("d", line); //使用线段生成器
var node = gBundle.selectAll(".node")
.data( nodes.filter(function(d) { return !d.children; }) )
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "rotate(" + (d.x- 90) + ")translate(" + d.y + ")" + "rotate("+ (90 - d.x) +")";
});
node.append("circle")
.attr("r", 20)
.style("fill",function(d,i){ return color(i); });
node.append("text")
.attr("dy",".2em")
.style("text-anchor", "middle")
.text(function(d) { return d.name; });
</script>
</body>
</html>
2、弦布局
2.1、简介:
弦图用来展示一组实体之间的关系,通过在不同的弧线之间画出二次贝塞尔曲线,将实体之间的关系表示在一张弦图中。下面展示了一个弦图,表示五个城市人口互相之间的来源关系,比如北京有2015人来自上海,上海有2060人来自广州。
2.2、demo:
2.3、代码:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>弦图</title>
<style>
body{
background-color: #000000;
}
</style>
</head>
<body>
<script src="../../d3.js"></script>
<script>
var city_name = ["北京","上海","广州","深圳","香港"];
var population = [
[1000,3015,4567,1234,3714],
[3214,2000,2060,124,3234],
[8761,6545,3000,8045,647],
[3211,1067,3214,4000,1006],
[2146,1034,6745,4764,5000]
];
var chord_layout = d3.layout.chord()
.padding (0.03)//取得或设置弦片段间的角填充,也就是每一个弦片段的间距啦
.sortSubgroups(d3.descending)
.matrix(population); // 取得或设置布局需要的关联矩阵数据
var width = 800,
height = 670;
var innerRadius = width/2*0.7,
outerRadius = innerRadius*1.1;
var color = d3.scale.category20();
var svg = d3.select("body").append("svg")
.attr("width",width)
.attr("height",height)
.append("g")
.attr("transform","translate("+width/2+","+height/2+")");
var outer_arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var g_outer = svg.append("g");
g_outer.selectAll("path")
.data(chord_layout.groups) //返回index(行索引)、subindex(列索引)、startAngle、endAngle、value
.enter()
.append("path")
.style("fill", function (d) {
return color(d.index)
}
)
.style("stroke", function (d) {
return color(d.index)
})
.attr("d",outer_arc);
g_outer.selectAll("text")
.data(chord_layout.groups)
.enter()
.append("text")
.each(function(d,i){
d.angle = (d.startAngle+ d.endAngle)/2;
d.name = city_name[i];
}) //表示对于任何一个绑定的元素,都执行后面的无名函数 function 的代码,这里的代码为: 计算一个角度,赋值给 d.angle ;获取城市的名称。
.attr("dy",".35em")
.attr("transform",function(d){
return "rotate("+(d.angle*180/Math.PI)+")"+"translate(0,"+-1.0*(outerRadius+10)+")"+((d.angle>Math.PI*3/4 && d.angle<Math.PI*5/4)?"rotate(180)":"");
})//在用 transform 进行位移时,要注意转换的顺序: rotate -> translate,最后一行转换代码表示:当角度在135°到225°之间时,旋转180°。否则下方的文字是倒的,不利于观看。
.text(function(d){return d.name;})
.style("stroke","white");
var inner_chord =