• D3的基本设计思路


    学习一项新技术,首先要搞清楚它的基本设计思路,有了这个宏观的技术架构,使用该技术起来,就会得心应手了。否则,就会不知道如何下手,即使看到人家的例子程序,可能也不知其所以然。

    下面,就简单的结合自己研究的官方文档,对D3的使用,给其基本设计思路,做一个简单的描述:

    在html文件中加载完官方的js插件d3.v3.min.js后:

    1.  设计画布(这里主要基于SVG介绍,当然,画布其实还有Canvas)。

         a. 主要包括SVG的大小,含有width,以及height。

         b. 通过d3全局对象,构建svg对象。

    2. 创建视图(D3支持的视图很多)

     1 [[bundle|捆绑布局]] - 对边使用Holten 层次捆绑算法。
     2 [[chord|弦布局]] - 从关系矩阵生成一个弦图。
     3 [[cluster|簇布局]] - 将实体聚集成树状图。
     4 [[force|力布局]] - 模拟物理力排放相连节点的位置。
     5 [[hierarchy|层次布局]] - 这是个抽象布局,可派生一个定制的层次布局。
     6 [[histogram|直方图布局]] - 使用量化的箱计算数据的分布。
     7 [[pack|包布局]] - 用递归的圆形包装生成一个层次布局。
     8 [[partition|分区布局]] - 递归地将节点树分割为旭日状或者冰柱状。
     9 [[pie|饼布局]] - 计算饼图或圆环图中弧的开始和结束角度。
    10 [[stack|堆叠布局]] - 计算堆叠图或者面积图的基线。
    11 [[tree|树布局]] - 整齐地排列树节点。注意簇布局不是整齐的。
    12 [[treemap|矩形树布局]] - 使用空间递归分区算法展示树的节点。

       例如:

              var tree = d3.layout.tree();

    3. 数据绑定

        其实,这一步做的事情,就是一个视图与数据的结合,视图将数据转化为该视图内定的数据结构,重点是添加了一些D3功能相关的辅助参数或者变量。 例如上例中的树视图,数据绑定后过程如下:

    1 var nodes = tree.nodes(root).reverse(),
    2 var links = tree.links(nodes);

    这个绑定,也可以说是数据转化,之后,nodes对象中不仅含有root这个原始数据(用户提供的输入数据),还含有D3系统需要的辅助参数,比如parent,depth等。

    4.  视图数据结合

         这一步,其实最能体现D3的设计思想,这一步涵盖的内容最为丰富,但是不多讲,重点介绍D3的特色操作enter,update,exit。

         a. 获取新的选择器(SVG灌入绑定数据后的新对象)

             例如: 

                   var node = svg.selectAll("g.node").data(nodes, function(d) { return d.id || (d.id = ++i); });

         b. enter/update/exit

            这三个概念是什么含义呢?

            如果数组为 [3, 6, 9, 12, 15],将此数组绑定到三个 p 元素的选择集上。可以想象,会有两个数据没有元素与之对应,这时候 D3 会建立两个空的元素与数据对应,这一部分就称为 Enter。而有元素与数据对应的部分称为 Update。如果数组为 [3],则会有两个元素没有数据绑定,那么没有数据绑定的部分被称为 Exit。

            例如下图:

            

            对于图形存在交互操作的情景,enter,update,以及exit都会用得到,例如我上一篇博客D3树状图异步按需加载数据里面的树状图,点击节点会有展开和收缩的效果,这个时候三者都会参与实际的逻辑处理。

            

         Update 和 Enter 的使用

            当对应的元素不足时 ( 绑定数据数量 > 对应元素 ),需要添加元素(append)。

            现在 body 中有三个 p 元素,要绑定一个长度大于 3 的数组到 p 的选择集上,然后分别处理 update 和 enter 两部分。

     1 var dataset = [ 3 , 6 , 9 , 12 , 15 ];
     2 
     3 //选择body中的p元素
     4 var p = d3.select("body").selectAll("p");
     5 
     6 //获取update部分
     7 var update = p.data(dataset);
     8 
     9 //获取enter部分
    10 var enter = update.enter();
    11 
    12 //update部分的处理:更新属性值
    13 update.text(function(d){
    14     return "update " + d;
    15 });
    16 
    17 //enter部分的处理:添加元素后赋予属性值
    18 enter.append("p")
    19     .text(function(d){
    20         return "enter " + d;
    21     });
    • update 部分的处理办法一般是:更新属性值
    • enter 部分的处理办法一般是:添加元素后,赋予属性值

         

        Update 和 Exit 的使用

          当对应的元素过多时 ( 绑定数据数量 < 对应元素 ),需要删掉多余的元素。

          现在 body 中有三个 p 元素,要绑定一个长度小于 3 的数组到 p 的选择集上,然后分别处理 update 和 exit 两部分。

          

     1 var dataset = [ 3 ];
     2 
     3 //选择body中的p元素
     4 var p = d3.select("body").selectAll("p");
     5 
     6 //获取update部分
     7 var update = p.data(dataset);
     8 
     9 //获取exit部分
    10 var exit = update.exit();
    11 
    12 //update部分的处理:更新属性值
    13 update.text(function(d){
    14     return "update " + d;
    15 });
    16 
    17 //exit部分的处理:修改p元素的属性
    18 exit.text(function(d){
    19         return "exit";
    20     });
    21 
    22 //exit部分的处理通常是删除元素
    23 // exit.remove();
    • exit 部分的处理办法一般是:删除元素(remove)

         到此, 入门D3,了解这个基本的框架,再去细读API文档或者教程,相对会容易些!

         最后,附带一个简单的例子,绘制环状图(显示资源占用比例的场景,还是很有使用价值的):

         

     1 <html>  
     2   <head>  
     3         <meta charset="utf-8">  
     4         <title>环装图</title>  
     5   </head> 
     6 
     7 <style>
     8 
     9 
    10 </style>
    11     <body>  
    12         <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>  
    13         <script>
    14         
    15         var width = 400;
    16         var height = 400;
    17         var dataset = [ 30 , 10 , 43 , 55 , 13 , 11, 100, 99];
    18         
    19         var svg = d3.select("body")
    20                     .append("svg")
    21                     .attr("width", width)
    22                     .attr("height", height);
    23         
    24         var pie = d3.layout.pie();
    25 
    26         var piedata = pie(dataset);
    27         
    28         var outerRadius = 150;    //外半径
    29         var innerRadius = 100;    //内半径,为100则中间没有空白
    30 
    31         var arc = d3.svg.arc()    //弧生成器
    32                     .innerRadius(innerRadius)    //设置内半径
    33                     .outerRadius(outerRadius);    //设置外半径
    34         
    35         var color = d3.scale.category20c();
    36         
    37         var arcs = svg.selectAll("g")
    38                       .data(piedata)
    39                       .enter()
    40                       .append("g")
    41                       .attr("transform","translate("+ (width/2) +","+ (width/2) +")");
    42                       
    43         arcs.append("path")
    44             .attr("fill",function(d,i){
    45                 return color(i);
    46             })
    47             .attr("d",function(d){
    48                 return arc(d);
    49             });
    50         
    51         arcs.append("text")
    52             .attr("transform",function(d){
    53                 return "translate(" + arc.centroid(d) + ")";
    54             })
    55             .attr("text-anchor","middle")
    56             .text(function(d){
    57                 return d.data;
    58             });          
    59         </script>  
    60         
    61     </body>  
    62 </html>  

  • 相关阅读:
    SpringBoot Schedule 配置
    ElasticSearch与Spring Boot集成问题
    Mybaits使用
    Java生成随机验证码
    Netty-FastThreadLocal快在哪里呢?
    直方图反向投影学习-----个人理解(你究竟是不是凶手)
    zookeeper启动报 Unexpected exception, exiting abnormally 错误
    upload三种上传方式(上)---Servlet---post---commons-fileupload.1.2.1.jar方式请求上传文件
    request.getRealPath为什么会被代替
    Java2E中的路径问题
  • 原文地址:https://www.cnblogs.com/shihuc/p/6065456.html
Copyright © 2020-2023  润新知