# arc生成器与chord生成器在chord布局中的使用详解

首先我们先来解释下arc生成器与chord生成器,其实所谓的生成器其实都是路径生成器的一种,在svg中有个标签元素,<path d=”“> </path>,我们发现有个d属性需要我们填写,我们当然可以自己填写,比如M0,0L1,1L2,2这些,但是这只是线段,如果弧,弦这种呢?根本就没法写,况且就算由点连成的线段写起来也很麻烦,与是d3给我们写了一个这样一系列函数,用来专门生成我们想要的图形路径字符串,这样很方便了有没有呢!!
路径生成器的种类有:line,arc,chord,area,diagonal,用法都很类似,学会了一个那么其他就很容易接受了。我们这一次主要讲arc,与chord

  • [ ] arc生成器

先看下代码,试着理解下

/*弧生成器 生成扇形一般用法*/
var width=200,height=200;
var data = [
                {startAngle:0,endAngle:2*Math.PI/3},
                {startAngle:2*Math.PI/3,endAngle:4*Math.PI/3},
                {startAngle:4*Math.PI/3,endAngle:2*Math.PI}  
            ];
//arc生成器对象
var arc = d3.svg.arc()
                  .innerRadius(0)  //定义内径
                  .outerRadius(90)//定义外径

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

//颜色比例尺
var color=d3.scale.category10();

//把path放到容器中,并给d赋属性
var arcGraph = svg.selectAll("g .arc")
                    .data(data)
                    .enter()
                    .append("g")
                    .attr("class","arc")
                    .append("path")
                    .attr("d",function(d){
                        return arc(d);    //arc对象包裹数据进去
                    })
                    .attr("stroke","white")
                    .attr("stroke-width",2)
                    .attr("fill",function(d,i){
                        return color(i);
                    })
                    .attr("transform","translate(100,100)");
    svg.append("g")
        .selectAll("text")
        .data(data)
        .enter()
        .append("text")
        .attr("transform",function(d){
            return "translate("+width/2+","+height/2+")"+
                   "translate("+arc.centroid(d)+")";    //取得arc路径的圆心

        })
        .attr("text-anchor","middle")
        .attr("fill","black")
        .attr("font-size",12)
        .text(function(d){
            return parseInt((d.endAngle-d.startAngle)*180/Math.PI+"'");
        })

arc生成器结果

其实我们也可以在定义arc的时候就将所有参数定义好,如下:

var arc = d3.svg.arc()
                  .innerRadius(0)  //定义内径
                  .outerRadius(90)//定义外径
                  .startAngle()  //角度是以0点为起始点,弧度为单位
                  .endAngle()

只不过这样定义就会不灵活,只能生成一个弧,所有的参数没法改变,如果作为数据绑定给path元素,将starAngel与endAngle动态传进去,那么久可以一次生成好多弧。总之最后d的参数,一定是所有的数据都要拥有, ,一般是第一种更多,更灵活。

  • [ ] chord生成器

还是先看下代码,试着理解编写者的用意

/*chord生成器*/
 var width=400,height=400;
 //一个chord必须要source与target 成对出现,一个source,一个target分别是一个弧,两个弧连线正好就是两条弦,所谓的chord生成器
var data = [
             {
                source:{startAngle:2*Math.PI/3,endAngle:4*Math.PI/3,radius:90},
                target:{startAngle:5*Math.PI/3,endAngle:6*Math.PI/3,radius:90}
            },
            {
                source:{startAngle:0,endAngle:1*Math.PI/3,radius:80},
                target:{startAngle:4*Math.PI/3,endAngle:5*Math.PI/3,radius:80}
            },



            ];

var chord = d3.svg.chord();

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

var color=d3.scale.category10();

//把path扔到容器中,并给d赋属性
var arcGraph = svg.selectAll("g .arc")
                    .data(data)
                    .enter()
                    .append("g")
                    .append("path")
                    .attr("d",chord)   //绑定chord对象
                    .attr("stroke","black")
                    .attr("stroke-width",2)
                    .attr("fill",function(d,i){
                        return color(i);
                    })
                    .attr("transform","translate(100,100)");

这里写图片描述

  • [ ] 布局讲解
    下面我们来看下chord布局,布局就是d3为我们写好的某个具体样式,其他还有如pie,chord,等,这些都是布局,将布局与路径生成器结合起来用,会更方便快捷。
    为了方便理解布局的共同特性,我们先来看下pie布局,最简单的这个
<style type="text/css">

text {
            font-family: sans-serif;
            font-size: 12px;
            fill: white;
        }

</style>
<body>

</body>
<script type="text/javascript">
var dataset = [ 5, 10, 20, 45, 6, 25 ];
var w=300;
var h=300;
var outerRadius=w/2;
var innerRadius=w/3;
/* arc路径生成器设定半径*/
var arc=d3.svg.arc()
              .innerRadius(innerRadius)
              .outerRadius(outerRadius)
/*定义一个pie*/
var pie=d3.layout.pie();

var color=d3.scale.category10();

var svg=d3.select("body")
          .append("svg")
          .attr("width",w)
          .attr("height",h)
/*开始对每个扇形(startAngle,endAngle,value)进行绑定,放在透明g元素中*/
var arcs=svg.selectAll("g.arc")
            .data(pie(dataset))
            .enter()
            .append("g")
            .attr("class","arc")
            .attr("transform","translate("+w/2+","+w/2+")")//放到svg中心
/*为每个g以弧参数生成路径*/
/*d当用布局的时候,就不需要再用路径生成器包裹数据了*/
arcs.append("path")
    .attr("fill",function(d,i){
        return color(i);
    })
    .attr("d",arc);

arcs.append("text")
    .attr("transform",function(d){
        return "translate("+arc.centroid(d)+")";
    })
    .attr("text-anchor","middle")
    .text(function(d){
        return d.value;
    })

</script>

pie布局结果
当我们console.log(pie(dataset))的结果,pie(data)为我们将数据,根据占比生成了所有arc需要的路径数据,结果如下图
这里写图片描述
总结成一句话就是,用布局包裹数据,会生成这个布局所需要的特定数据
最后,我们来看以arc生成器与chord生成器为前提的chord布局的使用
还是先看代码

<script type="text/javascript">
//注释掉的是数据样例,直观理解数据组成
/*数据说明:矩阵的值表示每个维度的相关性,如通信多少次,或者每个row由多少个coloumn组成*/
// var city_name = [ "北京" , "上海" , "广州" , "深圳" , "香港"  ];

// var population = [
//            北京    上海    
//       北京[ 3214,  2000 , 2060 , 124  , 3234 ],
//           [ 8761,  6545 , 3000 , 8045 , 647  ],
//           [ 3211,  1067 , 3214 , 4000 , 1006 ],
//           [ 2146,  1034 , 6745 , 4764 , 5000 ]
        // ];
/*chord上的数字,比如说2000,代表了北京人口中,上海人口占2000*/
//生成一个数据矩阵
var matrix=new Array(15);
for (var i=0;i<15;i++){
    matrix[i] = new Array(15)
    for (var j=0;j<15;j++){
      matrix[i][j]=parseInt(Math.random()*8);
    }
}
/*定义一个弦布局*/
console.log(matrix)
var chord_layout=d3.layout.chord()
                          .padding(0.05)   //弧间距
                          .sortSubgroups(d3.ascending())  //结点排序方式
                          .matrix(matrix);   //加载数据

/*拿到弧跟节点*/
//弦布局整合后的数据,一个是groups弧节点,四个字段:index,startangle(弧度为单位),endangle,value一个是弦数据,source与target,每个字段中又有index,subindex,startangle,endangle,value;

var groups=chord_layout.groups();  //包裹了arc数据
var chords=chord_layout.chords(); //包裹了chord数据
//可以在控制台看下
console.log(groups)   
console.log(chords)
/*svg画布*/
var width=500,height=400;

var svg=d3.select("body")
          .append("svg")
          .attr("width",width)
          .attr("height",height)
          .append("g")
          .attr("transform","translate("+width/2+","+height/2+")")


/*用弧生成器*/
var innerRadius=height/3.5,outerRadius=height/3;
var arc=d3.svg.arc()
              .innerRadius(innerRadius)
              .outerRadius(outerRadius);

var color=d3.scale.category20();

var g_outer=svg.append("g")

/*弧节点路径*/
g_outer.selectAll("path.arc")
       .data(groups)   //包裹所需数据
       .enter()
       .append("path")
       .attr("class","arc")
       .attr("d",arc)   //引用生成器
       .attr("fill",function(d,i){
            return color(d.index);
       })
       .attr("stroke",function(d,i){
            return color(d.index);
       })
/*弧外边文字*/
g_outer.selectAll("text .arc")
       .data(groups)
       .enter()
       .append("text")
       .attr("class","arc")
       .each(function(d,i){
          d.angle=(d.startAngle+d.endAngle)/2;
          d.name=i;
       })
       .attr("transform",function(d,i){
        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)" : "");
       })
       .attr("dy",".35em")
       .attr("text-anchor","middle")
       .text(function(d,i){
          return d.name;
       })

//内chord生成
var inner_chord=d3.svg.chord()
                      .radius(innerRadius)

svg.append("g")
   .selectAll("path .chord")
   .data(chords)    //绑定所需数据
   .enter()
   .append("path")
   .attr("class","chord")
   .attr("d",inner_chord)   //引用生成器
   .attr("opacity",0.7)
   .attr("fill",function(d,i){
        return color(d.source.index)

   })
   .on("mouseover",function(d,i){    //事件响应
        d3.select(this)
          .attr("fill",function(d,i){
            return "black";
          })
   })
   .on("mouseout",function(d,i){
        d3.select(this)
          .transition()
          . duration(1000)
          .attr("fill",function(d,i){
            return color(d.source.index);
          })
   })
   .append("title")
   .text(function(d) {
            return "This value is " + d.target.value;
         });



</script>

上边的代码告诉我们,一个chord布局为我们生成所需要的弧数据与弦数据,我们只需要引用各自的生成器就行了。
我们看下在代码中的两个控制台输出的数据
groups变量
arc
chord变量
chord
最后这个是最后生成的图
这里写图片描述

原文地址:https://www.cnblogs.com/caojunjie/p/8318887.html