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>  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM