D3.js 数据连接
数据连接是 D3.js 中的另一个重要概念。它与选择一起工作,使我们能够根据我们的数据集(一系列数值)操作 HTML 文档。默认情况下,D3.js 在其方法中赋予数据集最高优先级,数据集中的每一项都对应一个 HTML 元素。本章详细介绍了数据连接。
什么是数据联接?
数据连接使我们能够根据现有 HTML 文档中的数据集注入、修改和删除元素(HTML 元素以及嵌入的 SVG 元素)。默认情况下,数据集中的每个数据项对应于文档中的一个元素(图形)。
随着数据集的变化,相应的元素也可以轻松操作。数据连接在我们的数据和文档的图形元素之间建立了密切的关系。数据连接使得基于数据集的元素操作变得非常简单和容易。
数据连接如何工作?
数据连接的主要目的是将现有文档的元素与给定的数据集进行映射。它根据给定的数据集创建文档的虚拟表示,并提供使用虚拟表示的方法。让我们考虑一个简单的数据集,如下所示。
数据集有五个项目,因此可以映射到文档的五个元素。让我们使用选择器的 selectAll() 方法和数据连接的 data() 方法将其映射到以下文档的
li 元素。
HTML
<ul id = "list">
<li><li>
<li></li>
</ul>
D3.js 代码
d3.select("#list").selectAll("li").data([10, 20, 30, 25, 15]);
现在,文档中有五个虚拟元素。前两个虚拟元素是文档中定义的两个
li 元素,如下所示。
对于前两个
li,我们可以使用
attr()、style()、text()等所有选择器的元素修改方法,如下图.
d3.select("#list").selectAll("li")
.data([10, 20, 30, 25, 15])
.text(function(d) { return d; });
text() 方法中的函数用于获取
li 元素的映射数据。这里,
d 代表第一个
li 元素为 10,第二个
li 元素为 20。
接下来的三个元素可以映射到任何元素,并且可以使用数据连接的 enter() 和选择器的 append() 方法来完成。 enter() 方法可以访问剩余数据(未映射到现有元素),而 append() 方法用于从相应数据创建新元素。让我们也为剩余的数据项创建
li。数据图如下-
3. li-30
4. li-25
5. li-15
创建新的 li 元素的代码如下-
d3.select("#list").selectAll("li")
.data([10, 20, 30, 25, 15])
.text(function(d) { return "this is pre-existing element and the value is " + d; })
.enter()
.append("li")
.text(function(d)
{ return "this is dynamically created element and the value is " + d; });
Data join 提供了另一种称为
exit() 方法的方法来处理从数据集中动态删除的数据项,如下所示。
d3.selectAll("li")
.data([10, 20, 30, 15])
.exit()
.remove()
这里,我们使用 exit() 和 remove() 方法从数据集中删除了第四项及其对应的 li。
完整代码如下-
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
<style>
body { font-family: Arial; }
</style>
</head>
<body>
<ul id = "list">
<li></li>
<li></li>
</ul>
<input type = "button" name = "remove" value = "Remove fourth value"
onclick = "javascript:remove()" />
<script>
d3.select("#list").selectAll("li")
.data([10, 20, 30, 25, 15])
.text(function(d)
{ return "this is pre-existing element and the value is " + d; })
.enter()
.append("li")
.text(function(d)
{ return "this is dynamically created element and the value is " + d; });
function remove() {
d3.selectAll("li")
.data([10, 20, 30, 15])
.exit()
.remove()
}
</script>
</body>
</html>
以上代码的结果如下-
第四项被移除
数据连接方法
数据连接提供以下四种方法来处理数据集-
数据()
数据()
输入()
退出()
让我们详细介绍每种方法。
datum() 方法
datum() 方法用于为 HTML 文档中的单个元素设置值。一旦使用选择器选择元素,它就会被使用。例如,我们可以使用 select() 方法选择现有元素(p 标签),然后使用 datum() 方法设置数据。设置数据后,我们可以更改所选元素的文本或添加新元素并使用 datum() 方法设置的数据分配文本。
创建一个页面"datajoin_datum.html"并添加以下代码-
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<p></p>
<div></div>
<script>
d3.select("p")
.datum(50)
.text(function(d) {
return "Used existing paragraph element and the data " + d + " is assigned.";
});
d3.select("div")
.datum(100)
.append("p")
.text(function(d) {
return "Created new paragraph element and the data " + d + " is assigned.";
});
</script>
</body>
</html>
以上代码的输出如下。
data() 方法
data() 方法用于将数据集分配给 HTML 文档中的元素集合。一旦使用选择器选择了 HTML 元素,就会使用它。在我们的列表示例中,我们使用它来设置
li 选择器的数据集。
d3.select("#list").selectAll("li")
.data([10, 20, 30, 25, 15]);
enter() 方法
enter() 方法输出之前不存在图形元素的数据项集。在我们的列表示例中,我们使用它来创建新的
li 元素。
d3.select("#list").selectAll("li")
.data([10, 20, 30, 25, 15])
.text(function(d) { return "this is pre-existing element and the value is " + d; })
.enter()
.append("li")
.text(function(d) { return "this is dynamically created element and the value is " + d; });
exit() 方法
exit() 方法输出不再存在数据的图形元素集。在我们的列表示例中,我们使用它通过删除数据集中的数据项来动态删除
li 元素之一。
function remove() {
d3.selectAll("li")
.data([10, 20, 30, 15])
.exit()
.remove()
}
数据函数
在DOM操作一章中,我们了解了D3.js中不同的DOM操作方法,例如
style()、text()等。这些函数中的每一个通常都以一个常量值作为它的范围。然而,在
数据连接的上下文中,它需要一个匿名函数作为参数。这个匿名函数使用 data() 方法获取相应的数据和数据集的索引。因此,将为绑定到 DOM 的每个数据值调用这个匿名函数。考虑下面的 text() 函数。
.text(function(d, i) {
return d;
});
在这个函数中,我们可以应用任何逻辑来操作数据。这些是匿名函数,这意味着没有与函数关联的名称。除了 data (d) 和 index (i) 参数,我们可以使用
this 关键字访问当前对象,如下所示-
.text(function (d, i) {
console.log(d); // the data element
console.log(i); // the index element
console.log(this); // the current DOM object
return d;
});
考虑以下示例。
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
<style>
body { font-family: Arial; }
</style>
</head>
<body>
<p></p>
<p></p>
<p></p>
<script>
var data = [1, 2, 3];
var paragraph = d3.select("body")
.selectAll("p")
.data(data)
.text(function (d, i) {
console.log("d: " + d);
console.log("i: " + i);
console.log("this: " + this);
return "The index is " + i + " and the data is " + d;
});
</script>
</body>
</html>
上面的脚本将生成以下结果-
在上面的例子中,参数"d"给你你的数据元素,"i"给你数组中数据的索引,"this"是当前DOM元素的引用。在这种情况下,它是段落元素。请注意,我们在上面调用了 .data(data) 函数。data() 函数为所选元素提供数据,在我们的例子中是数据数组。