1. 程式人生 > >D3.js 的頁面元素生成

D3.js 的頁面元素生成

靜態生成元素

程式碼----------------------------------------------

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="./d3/d3.js"></script>
</head>
<body>
<script type="text/javascript">
d3.select("body")


.append("p")
.text("this is test");
</script>
</body>
</html>

輸出----------------------------------------------

this is test

---------------------------------------------------

分析程式碼:

  • select() 

        傳入一個CSS選擇符作為輸入,它會返回一個對DOM中匹配的第一個元素的引用(用selectAll()方法獲取多個元素)。

以這裡為例子,這裡取得文件的body元素,然後把它的引用交給呼叫鏈中的下一個方法。

  • append()

        建立一個你指定的新DOM元素,然後將它追加到呼叫它的元素末尾。這裡因為呼叫的是body,所以結果就是在body元素內部追加一個p元素。

  • text()

        接受一個字串,把它插入當前元素的開始和結束標籤之間,因為上面傳遞過來的時p元素,所以這裡會把資料插入到<p></p>之間。

        這一段程式碼是順序執行的

        即:<body></body> → <body><p></body> → <body><p>"this is test"</p></body>

---------------------------------------------------

 

動態生成元素

        上面的案例我們可以知道,元素和資料是一一關聯的。將上例黑體字改為如下:

---------------------------------------------------

dataset = [ 5, 10, 15, 20, 25 ];
d3.select("body")
.append("p")
.text(dataset);

輸出----------------------------------------------

5,10,15,20,25

---------------------------------------------------

        整個陣列作為了一個數據,與<p></p>元素對應。如果我們希望每個段落顯示一個值,我們會發現對應的元素不存在。這需要解決D3使用時的一個常見問題:如何選擇還不存在的元素?

---------------------------------------------------

dataset = [ 5, 10, 15, 20, 25 ];
d3.select("body").selectAll("p")
.data(dataset)
.enter()
.append("p")

.text(function(d) {return d;});

輸出----------------------------------------------

5

10

15

20

25

---------------------------------------------------

分析程式碼:

        雖然每個函式的功能查到了,但是對這裡資料流的過程我不是太懂。D3是資料流驅動的 JS 庫,我會在其他的地方嘗試理解這個過程。

  • seclectAll("p")

        選擇DOM中的所有段落,因為還沒有段落,所以返回空元素。可以認為這個空元素代表“馬上就可以建立的段落P”

  • data.(dataset)

        解析並數出資料值。其中,dataset 一共有5個值。因此此後的所有方法都將執行5遍,每次針對一個值。通常這個操作用於繫結一個數組到選擇集上,陣列的各項值分別與選擇集的各元素繫結。

  • enter()

        要建立新的繫結資料的元素,必須使用 enter()。這個方法會分析當前選擇的DOM元素和傳給他的資料,如果資料值比對應的DOM多,就建立一個新的佔位元素。然後把這個新佔位元素的引用交給鏈的下一個方法。

也就是說,當對應的元素不足的,通過enter() 增加元素,通常與 append() 函式一起用。

  • append("p")

       取得由 enter() 建立的空佔位元素,並把一個 p 元素追加到相應的 DOM中。然後他再把自己剛建立的元素交給鏈的下一個方法。

  • function(d) {return d;};

       function(d) {return d;} 是匿名函式,因為沒有名字。如果把函式儲存在一個變數中,那麼就成了命名函式 var dosomething = function() { // 執行程式碼 } 。這種函式也叫自定義函式,通常用於資料的操作。

        只要呼叫了 data() ,就會建立一個接收 d 為輸入的匿名函式。與當前元素對應,隨著 D3 遍歷每個元素,d 的這個值也會跟著變化。實際上,如果不把 d 封裝在匿名函式裡, d 就沒有值。由於 D3 中如 text() ,attr() 以及很多方法,都可以接收函式作為引數。如果 D3 發現傳入的是一個匿名函式,就會呼叫它,同時將當前數值 d 作為引數傳進函式中。實際上,D3 只關心有一個引數,有一個引數才能把當前資料值傳進來,這個值叫 d 叫 info 叫 datum 都無所謂。

---------------------------------------------------

新增樣式

以 style() 為例,可以設定取得的元素的 CSS屬性。在上面的例子裡新增程式碼如下:

---------------------------------------------------

.style("color","red");

輸出----------------------------------------------

5

10

15

20

25

---------------------------------------------------

        很有意思的一點,這句話要放在.text()的最後面。因為d3 是資料驅動元素。如果放在前面,此時資料還沒讀取,還未與元素繫結。換句話說,html 頁面還沒生成,這個時候對 css 進行改動是不起作用的。

        由於上文中說到,function(d) 通常用於資料操作,d 為接收函式的引數。所以對sytle() 我們也可以將顏色引數改為一個匿名函式進行資料處理:

---------------------------------------------------

.style("color",function(d){
if (d > 15) {
return "red";
} else {
return "black";
}
});

輸出----------------------------------------------

5

10

15

20

25

---------------------------------------------------