开始使用JavaScript和D3库进行数据可视化
介绍
D3.js 或 D3 是一个 JavaScript 库。 它的名字代表Data-Driven Documents(3个“D”),它被称为交互式动态数据可视化库网。
D3 的第 4 版于 2011 年 2 月首次发布,于 2016 年 6 月发布。 在撰写本文时,最新的稳定版本是 4.4 版,并且还在不断更新中。
D3 利用 Scalable Vector Graphic 或 SVG 格式,它允许您渲染可以放大或缩小而不会损失质量的形状、线条和填充。
本教程将指导您使用 JavaScript D3 库创建条形图。
先决条件
要充分利用本教程,您应该熟悉 JavaScript 编程语言以及 CSS 和 HTML 知识。
尽管您将使用 CSS 来设置 D3 的样式,但值得注意的是,许多适用于 HTML 的标准 CSS 在 SVG 上的工作方式不同——也就是说,您将使用 stroke
而不是 [X183X ] 和 fill
而不是 color
。 要了解更多信息,您可以阅读关于 SVG 和 CSS 的 Mozilla 开发者网络文章。
我们将使用文本编辑器和网络浏览器。 出于测试目的,建议使用工具来检查和调试 JavaScript、HTML 和 CSS,例如 Firefox Developer Tools 或 Chrome DevTools。
第 1 步 — 创建文件和参考 D3
让我们首先创建一个目录来保存我们所有的文件。 你可以随便叫它,我们这里叫它D3-project。 创建完成后,进入目录。
mkdir D3-project cd D3-project
要使用 D3 的功能,您必须在网页中包含 d3.js
文件。 它大约有 16,000 行长和 500kb。
让我们使用 curl
将文件下载到我们的目录。
要下载更适合包含在您的项目中的压缩版本,请键入:
curl https://d3js.org/d3.v4.min.js --output d3.min.js
如果您打算阅读 D3 代码,最好通过键入以下内容来获得带有人类友好空格的未压缩版本:
curl https://d3js.org/d3.v4.js --output d3.js
我们将在本教程中使用 d3.min.js
文件,但如果您选择使用人类可读的版本,请在您的 HTML 文件中引用 d3.js
。
因为 D3 版本 4 是模块化的,所以您可以选择通过仅拉入您将使用的模块来减小文件大小。
下载 D3 后,让我们设置 CSS 和 HTML 文件。 您可以选择您想在此文件上使用的任何文本编辑器,例如 nano
。 我们将从 CSS 文件 style.css
开始,以便我们可以立即从 HTML 文件链接到它。
nano style.css
我们将从一个标准的 CSS 声明开始,以 100% height 和无边距设置页面样式。
html, body { margin: 0; height: 100%; }
您现在可以保存并关闭 CSS 文件。
接下来我们将创建我们的 JavaScript 文件,我们将其命名为 barchart.js
,因为我们将为这个示例制作一个条形图。 这个文件是我们大部分 D3 工作的存放位置,我们将在下一步中开始处理。 由于我们现在不需要打开文件,可以使用 touch
命令。
touch barchart.js
现在,让我们将所有这些元素连接到一个 HTML 文件,我们称之为 barchart.html
:
nano barchart.html
我们可以像大多数其他 HTML 文件一样设置此文件,在其中我们将引用我们刚刚创建的 style.css
和 barchart.js
文件以及 d3.min.js
脚本。
条形图.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Bar Chart</title> <link rel="stylesheet" type="text/css" href="style.css"> <!-- Alternatively use d3.js here --> <script type="text/javascript" src="d3.min.js"></script> </head> <body> <script type="text/javascript" src="barchart.js"></script> </body> </html>
现在可以保存和关闭 HTML 文件。
第 2 步 — 在 JavaScript 中设置 SVG
我们现在可以使用我们选择的文本编辑器打开 barchart.js
文件:
nano barchart.js
让我们从添加一个数字数组开始,我们将使用它作为条形图的基础:
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30];
接下来,我们需要创建 SVG 元素。 这是我们将放置所有形状的地方。 在 D3 中,我们使用 d3.select
告诉浏览器搜索元素。
我们可以用单行 d3.select("body").append("svg");
来做到这一点,但如果我们将它声明为一个变量会更好,这样我们以后可以在代码中方便地引用它。
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg");
如果我们现在将 barchart.html
加载到我们选择的 Web 浏览器中,我们应该能够使用我们的开发工具并将鼠标悬停在 SVG 框上来检查 DOM 或 Document Object Model。 根据您的浏览器,它可能非常小。
回到我们的 JavaScript 文件,我们可以将 attributes 链接到 SVG 以使其成为网页的完整高度和宽度。 我们将使用 .attr()
作为属性。 尽管我们可以将这一切都放在一行中,但将其分解会更具可读性。 确保将分号向下移动到变量声明的末尾。
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%");
如果您在浏览器中重新加载页面,当您将鼠标悬停在 DOM 上时,您应该会看到一个占据整个屏幕的矩形。
第 3 步 — 添加矩形
准备好 SVG 后,我们可以开始将数据集的矩形添加到 JavaScript 文件中。
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%"); svg.selectAll("rect") .data(dataArray) .enter().append("rect");
就像上面的 d3.select
一样,我们告诉浏览器搜索元素。 这一次,它是一个矩形数组。 因为它是一个数组,所以我们使用 d3.selectAll
并且我们使用 d3.selectAll("rect")
因为它是一个矩形数组。 如果浏览器找到矩形,它将在选择中返回它们,如果它是空的,它将返回空。 使用 D3,您必须首先选择要操作的元素。
我们使用 .data(dataArray)
将此矩形数组与存储在 dataArray
中的数据联系起来。
要实际为选择中的每个项目添加一个矩形(对应于数据数组),我们还将添加 .enter().append("rect");
以附加矩形。 在此示例中,将有 9 个矩形对应于数组中的 9 个数字。
如果你现在重新加载你的页面,你还不会看到任何矩形,但是如果你检查 DOM,你会看到那里定义了 9 个矩形。
我们还没有为矩形设置属性以使它们可见,所以让我们添加它们。
设置形状的属性
我们可以使用 .attr()
以与定义 SVG 属性相同的方式向形状添加属性。 D3 中的每个形状都将具有不同的属性,具体取决于它们的定义和绘制方式。
我们的矩形将包含 4 个属性:
("height", "height_in_pixels")
矩形的高度("width", "width_in_pixels")
表示矩形的宽度("x", "distance_in_pixels")
表示它们与浏览器窗口左侧的距离("y", "distance_in_pixels")
表示它们与浏览器窗口顶部的距离
因此,如果我们想要一个长 250 像素、宽 40 像素、距浏览器左侧 25 像素、距顶部 50 像素的矩形,我们将编写如下代码:
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%"); svg.selectAll("rect") .data(dataArray) .enter().append("rect") .attr("height","250") .attr("width","40") .attr("x","25") .attr("y","50");
如果我们刷新浏览器,我们会看到所有的矩形重叠:
默认情况下,D3 中的形状填充为黑色,但我们可以稍后修改它,因为我们需要首先解决矩形的位置和大小。
使矩形反映数据
目前,我们数组中的所有矩形都在 X 轴上具有相同的位置,并且不代表高度方面的数据。
要修改矩形的位置和大小,我们需要为我们的一些属性引入 functions。 添加功能将使值动态而不是手动。
让我们从修改 x
属性开始。 目前该行代码如下所示:
.attr("x","25")
我们将用函数替换 25 像素的图形。 我们将 D3 定义的两个变量传递给 function()
,分别代表数据点和索引。 索引告诉我们数据点在数组中的位置。 按照惯例,使用 d
作为数据点,使用 i
作为索引,如 function(d, i)
,但你可以使用任何你想要的变量。
JavaScript 将遍历 d
和 i
。 让我们为其迭代的每个索引添加间距,以便每个矩形都有间距。 为此,我们可以将索引 i
乘以一定数量的像素。 我们现在将使用 60,但您可以决定哪种间距适合您。 我们的 X 轴属性的新行现在看起来像这样:
.attr("x", function(d, i) {return i * 60;})
但是,如果我们现在运行代码,我们会看到矩形与浏览器的左侧齐平,所以让我们在此处添加一些额外的间距,例如距离边缘 25 像素。 现在我们的完整代码应该是这样的:
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%"); svg.selectAll("rect") .data(dataArray) .enter().append("rect") .attr("height","250") .attr("width","40") .attr("x", function(d, i) {return (i * 60) + 25}) .attr("y","50");
如果此时我们刷新浏览器,我们将看到如下所示的内容:
现在我们的矩形沿 X 轴间隔开来,代表我们数组中的每个项目。 接下来,让矩形的高度反映数组中的数据。
我们现在将使用 height
属性,并将添加一个类似于我们添加到 x
属性的函数。 让我们首先将变量 d
和 i
传递给 function
,然后返回 d
。 回想一下 d
代表数据点。
.attr("height", function(d, i) {return (d)})
如果您现在运行代码,您会注意到两件事。 首先,矩形相当小,其次它们附加到图表的顶部而不是底部。
为了解决矩形的小尺寸问题,让我们将返回的 d
相乘:
.attr("height", function(d, i) {return (d * 10)})
现在矩形的大小变大了,但它们仍然从上到下显示。
浏览器通常从左上到右下阅读网页,而我们从下到上阅读条形图。 要重新定位矩形,我们将修改 y
属性以减去顶部的空间。
同样,我们将使用 function(d, i)
,我们将返回一个高于条形图最高值的 Y 值,比如 400。 我们将从 400 中减去返回的 (d * 10)
的高度,因此我们的行现在看起来像这样:
.attr("y", function(d, i) {return 400 - (d * 10)});
让我们看看我们完整的 JavaScript 代码:
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%"); svg.selectAll("rect") .data(dataArray) .enter().append("rect") .attr("height", function(d, i) {return (d * 10)}) .attr("width","40") .attr("x", function(d, i) {return (i * 60) + 25}) .attr("y", function(d, i) {return 400 - (d * 10)});
此时,当我们重新加载页面时,我们会看到一个可以从下到上阅读的条形图:
现在,我们可以对图表进行样式设置。
第 4 步 — 使用 D3 进行样式设置
我们将使用 CSS 文件来设置 D3 形状的样式,但首先,为了使这项工作更容易,我们将在 JavaScript 文件中为矩形指定一个类名,我们可以在 CSS 文件中引用该类名。
添加一个类就像使用点符号添加任何其他属性一样。 我们将调用类 bar
,因为它是一个条形图,但我们可以随意调用它,只要所有引用都引用相同的名称。 我们的语法将如下所示:
.attr("class", "bar")
我们可以在任何我们想要的地方添加这个属性。 将其保留为第一个属性可以使其更容易在我们的 CSS 文件中引用。
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%"); svg.selectAll("rect") .data(dataArray) .enter().append("rect") .attr("class", "bar") .attr("height", function(d, i) {return (d * 10)}) .attr("width","40") .attr("x", function(d, i) {return (i * 60) + 25}) .attr("y", function(d, i) {return 400 - (d * 10)});
现在,让我们切换到我们的 style.css
文件,目前看起来像这样:
样式.css
html, body { margin: 0; height: 100% }
我们可以通过改变填充颜色来修改我们的矩形,引用我们刚刚创建的 bar
类:
样式.css
html, body { margin: 0; height: 100% } .bar { fill: blue }
在这里,我们将矩形设为蓝色,我们也可以为它们分配一个十六进制颜色代码,如下所示:
.bar { fill: #0080FF }
此时,我们的矩形看起来像这样:
我们可以为矩形赋予附加值,例如 stroke
以特定颜色勾勒矩形,以及 stroke-width
:
样式.css
html, body { margin: 0; height: 100% } .bar { fill: #0080FF; stroke: black; stroke-width: 5 }
这将为我们的矩形提供一个宽度为 5 像素的黑色轮廓。
此外,我们可以通过为条形颜色添加样式以在鼠标悬停时更改来为图表添加一点交互性:
.bar:hover { fill: red }
现在,当我们将鼠标悬停在其中一个矩形上时,该特定矩形将变为红色:
或者,您可以通过添加其他属性来设置 JavaScript 文件中的形状样式。 在矩形块中,我们将像其他 .attr()
属性一样编写这些。 因此,在矩形周围添加黑色笔划将被写为 .attr("stroke", "black")
。 让我们还添加一个 5 像素的 stroke-width
,并确保将分号向下移动。
条形图.js
... svg.selectAll("rect") .data(dataArray) .enter().append("rect") .attr("class", "bar") .attr("height", function(d, i) {return (d * 10)}) .attr("width","40") .attr("x", function(d, i) {return (i * 60) + 25}) .attr("y", function(d, i) {return 400 - (d * 10)}) .attr("stroke", "black") .attr("stroke-width", "5");
选择取决于您决定如何设置形状的样式以及在什么文件中。 在此示例中,我们将在 style.css
文件中工作,并将其限制为填充颜色和悬停填充:
样式.css
html, body { margin: 0; height: 100% } .bar { fill: #0080FF } .bar:hover { fill: #003366 }
在网络上使用颜色时,重要的是要牢记您的受众并努力包含尽可能普遍可访问的颜色。 要了解有关颜色可访问性注意事项的更多信息,您可以查看可访问性和我 .
第 5 步 - 添加标签
我们的最后一步是以标签的形式在我们的图表中添加一些可量化的标记。 这些标签将对应于我们数组中的数字。
添加文本类似于添加我们上面所做的矩形形状。 我们需要选择文本,然后将其附加到 SVG。 我们还将它绑定到我们创建的 dataArray
。 我们将使用 "text"
而不是 "rect"
,但一般格式类似于我们在上面添加矩形时所做的。 我们将这些行添加到我们的 barchart.js
文件的底部。
条形图.js
var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%"); svg.selectAll("rect") .data(dataArray) .enter().append("rect") .attr("class", "bar") .attr("height", function(d, i) {return (d * 10)}) .attr("width","40") .attr("x", function(d, i) {return (i * 60) + 25}) .attr("y", function(d, i) {return 400 - (d * 10)}); svg.selectAll("text") .data(dataArray) .enter().append("text") .text(function(d) {return d;});
当我们刷新浏览器时,我们不会在页面上看到任何文本,但我们会在 DOM 中再次看到它:
如果将鼠标悬停在 DOM 中的文本行上,您会看到文本都位于页面顶部,其中 X 和 Y 等于 0。 我们将通过添加属性使用与矩形相同的函数公式来修改位置。
条形图.js
... svg.selectAll("text") .data(dataArray) .enter().append("text") .text(function(d) {return d}) .attr("x", function(d, i) {return (i * 60) + 25}) .attr("y", function(d, i) {return 400 - (d * 10)});
当您现在加载网页时,您会看到数字浮动在条形上方。
值得注意的是,因为这是 SVG 而不是图像,所以您可以像在页面上看到的任何其他文本一样选择文本。
从这里,您可以通过修改函数公式开始重新定位数字。 您可能希望让它们漂浮在条形上方,例如:
条形图.js
... svg.selectAll("text") .data(dataArray) .enter().append("text") .text(function(d) {return d}) .attr("x", function(d, i) {return (i * 60) + 36}) .attr("y", function(d, i) {return 390 - (d * 10)});
或者,您可以通过修改其在 Y 轴方面的位置,让数字漂浮在矩形本身上。 我们还想让它更具可读性,所以让我们添加一个可以从我们的 style.css
文件中访问的类。
条形图.js
... svg.selectAll("text") .data(dataArray) .enter().append("text") .text(function(d) {return d}) .attr("class", "text") .attr("x", function(d, i) {return (i * 60) + 36}) .attr("y", function(d, i) {return 415 - (d * 10)});
在我们的 style.css
文件中,我们将通过在文件底部添加以下行来使文本变为白色和无衬线。
样式.css
... .text { fill: white; font-family: sans-serif }
您可以通过定位和样式随意修改文本。 例如,您可能还想更改 style.css
文件中的 font-size
属性。
完成的代码和代码改进
此时,您应该在 JavaScript 的 D3 库中呈现了一个功能齐全的条形图。 让我们看看我们所有的代码文件。
条形图.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Bar Chart</title> <!-- Reference style.css --> <link rel = "stylesheet" type="text/css" href="style.css"> <!-- Reference minified version of D3 --> <script type="text/javascript" src="d3.min.js"></script> </head> <body> <script type="text/javascript" src="barchart.js"></script> </body> </html>
样式.css
html, body { margin: 0; height: 100% } /*Rectangle bar class styling*/ .bar { fill: #0080FF } .bar:hover { fill: #003366 } /*Text class styling*/ .text { fill: white; font-family: sans-serif }
条形图.js
// Create data array of values to visualize var dataArray = [23, 13, 21, 14, 37, 15, 18, 34, 30]; // Create variable for the SVG var svg = d3.select("body").append("svg") .attr("height","100%") .attr("width","100%"); // Select, append to SVG, and add attributes to rectangles for bar chart svg.selectAll("rect") .data(dataArray) .enter().append("rect") .attr("class", "bar") .attr("height", function(d, i) {return (d * 10)}) .attr("width","40") .attr("x", function(d, i) {return (i * 60) + 25}) .attr("y", function(d, i) {return 400 - (d * 10)}); // Select, append to SVG, and add attributes to text svg.selectAll("text") .data(dataArray) .enter().append("text") .text(function(d) {return d}) .attr("class", "text") .attr("x", function(d, i) {return (i * 60) + 36}) .attr("y", function(d, i) {return 415 - (d * 10)});
这段代码可以正常工作,但是您可以做很多事情来改进代码。 例如,您可以利用 SVG 组元素将 SVG 元素组合在一起,从而允许您用更少的代码行来修改文本和矩形。
您还可以通过不同方式访问数据。 我们使用一个数组来保存我们的数据,但您可能想要可视化您已经可以访问的数据,并且它可能比在数组中正常工作的数据要多得多。 D3 将允许您使用几种不同的数据文件类型:
- HTML
- JSON
- 纯文本
- CSV(逗号分隔值)
- TSV(制表符分隔值)
- XML
例如,您可以在网站目录中有一个 JSON 文件并将其连接到 JavaScript 文件
d3.json("myData.json", function(json) { // code for D3 charts in here });
您还可以将 D3 库与您可能已经从 vanilla JavaScript 知道的其他交互功能结合起来。
结论
本教程介绍了如何在 JavaScript D3 库中创建条形图。 您可以通过访问 GitHub 上的 D3 API 了解有关 d3.js 的更多信息。
其他编程语言提供了其他方法来可视化数据,不仅限于 Web 浏览器。 从这里,您可以学习如何使用 matplotlib 通过 Python 绘制数据。