d3.js——弦图的绘制

首先我们要明白弦图所要表达的意思是什么?比如我们有以下一组关于地区人口的数据:

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]
];
我们可以将上面的数据绘制成如下的表格,比如第2行第4列表示为:上海的人口中有2060人来自广州。所以弦图就是将这些有关联的数据进行可视化。
  北京 上海 广州 深圳 香港
北京 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

有了数据源之后,还是和之前的一样,我们首先要做的就是使用d3.layout.chord()进行数据转换:

var chord_layout = d3.layout.chord()
    .padding (0.03)//取得或设置弦片段间的角填充,也就是每一个弦片段的间距啦
    .sortSubgroups(d3.descending) //取得或设置用于子分组的比较器。d3.descending(a, b),如果a > b返回-1,a < b返回1,a = b返回0。 这是固有的比较器方法,也可用于关联内置数组排序的方法来给元素降序排序:
    .matrix(population); // 取得或设置布局需要的关联矩阵数据
然后我们来做常规的一些定义:

var width = 600,
    height = 600;
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;});
最后我们来进行内部弦的绘制同时添加一些鼠标事件效果。这里添加内部弦有专用的函数d3.svg.chord(),只要将转换后的参数传给此函数,即可做内部弦:

var inner_chord = d3.svg.chord()
    .radius(innerRadius);

svg.append("g")
    .attr("class","chord")
    .selectAll("path")
    .data(chord_layout.chords) //返回index(行索引)、subindex(列索引)、startAngle、endAngle、value等参数
    .enter()
    .append("path")
    .attr("d",inner_chord)
    .style("fill", function(d) { return color(d.source.index); })
    .style("opacity",0.5)
    .on("mouseover",function(d,i){
        d3.select(this)
            .style("fill","yellow");
    })
    .on("mouseout",function(d,i){
        d3.select(this)
            .transition()
            .duration(1000)
            .style("fill",color(d.source.index))
    })
静态图如下:
d3.js——弦图的绘制_第1张图片






你可能感兴趣的:(d3,鼠标事件,弦图,layout.chord,chord.chords)