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
---------------------------------------------------