静态生成元素
<!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") .append("p") .text(dataset);
输出----------------------------------------------
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属性。在上面的例子里添加代码如下:
dataset = [ 5, 10, 15, 20, 25 ]; d3.select("body") .append("p") .text(dataset);
输出----------------------------------------------
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
---------------------------------------------------