# 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
最後這個是最後生成的圖
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章