• # 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
    最后这个是最后生成的图
    这里写图片描述

  • 相关阅读:
    利用Airtest开发爬虫
    添加mitmproxy证书为安卓系统证书(模拟器亦可)
    mac下 安卓模拟器抓包推荐
    mac上appium连接ios
    HomeBrew和HomeBrew Cask的安装和使用
    NOIP2020 游记
    CSP2020 游记
    随机数之 xorShift128Plus 板子
    最大单词长度乘积(力扣第318题)
    两个整数之和(力扣第371题)
  • 原文地址:https://www.cnblogs.com/caojunjie/p/8318887.html
Copyright © 2020-2023  润新知