D3.js 入门
使用强大的 D3.js 进行数据可视化入门。
在本教程中,我们将学习以下内容。
- D3是什么?
- 为什么要使用D3?
- D3 中的形状、辅助元素和比例尺
- 在 D3 中创建散点图
1. D3是什么?
数据驱动文档(Data Driven Documents,简称 D3)是一个强大的 JavaScript 库,它使用 HTML、Canvas 和 SVG 等常见 Web 标准来构建数据可视化。D3 允许您将数据绑定到 DOM,然后对文档应用数据驱动的转换,例如 CSS 属性和 SVG。
D3.js 由Mike Bostock、Vadim Ogievetsky 和 Jeff Heer 于 2011 年初创建。它是一个庞大的 JavaScript 库,由 Mike Bostock 在GitHub上积极管理。
2. 为什么要使用D3?
一、做出数据驱动的决策
可视化可以帮助企业过滤掉干扰信息,看清数据趋势。D3.js 不仅仅是一个图表库,它还提供了多种可视化工具,包括静态和交互式图表,让您可以按照自己的方式查看数据。
二、动态且数据绑定
D3 允许你将数据绑定到DOM,因此可视化效果会随着数据而变化。
三、操作SVG
D3 可视化基于 SVG,这是一种基于 XML 的文本格式,用于描述图像的显示方式。
下图展示了 SVG 中的线条、圆形和矩形。
<svg>
<line x1="40" y1="20" x2="40" y2="160" style="stroke-width: 1; stroke: black;"/>
<circle cx="100" cy="80" r="20" fill="green" />
<rect x="140" y="25" width="30" height="200" fill="red" />
</svg>
SVG 是基于矢量的,因此可以缩放而不会损失质量或出现像素化。有关其他 SVG 元素的更多信息,请点击此处。
四、大量示例
D3 提供了数千个示例供您参考,从简单的条形图到复杂的沃罗诺伊图,应有尽有。

来源:http ://christophermanning.org/gists/1734663/
更多示例可在 D3图库中查看。
五、开源!
D3 是一个开源库,其源代码托管在GitHub上。它是 GitHub 上星标数和fork 数最高的仓库之一,并有数百位开发者为其做出贡献。它还支持其他开发者构建的对 React 和 Leaflet 等其他 JavaScript 库的封装。
3. D3 中的形状、辅助元素和比例尺
一、形状
正如我们上面看到的,创建单个形状非常繁琐。想象一下,要绘制一个包含数百个点的散点图,并将它们与坐标轴对齐!D3 会处理这些基本的图表绘制工作,让您可以专注于实际的可视化效果。在深入绘制散点图之前,让我们先在 D3 中重新创建这些形状。
首先,我们定义一个 SVG 元素来容纳各种形状。这个 SVG 元素可以添加到 DOM 中的任何元素上。接下来,我们添加圆形、矩形和直线。
<!DOCTYPE html>
<html>
<head>
<title>Shapes in D3</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="canvas"></div>
<script>
var canvas = d3.select("#canvas") // D3 uses a jQuery like selector
.append("svg")
.attr("height", 500)
.attr("width", 500);
var circle = canvas.append("circle") // Appending shape elements to the SVG element
.attr("cx", 250)
.attr("cy", 250)
.attr("r", 100)
.attr("fill", "red");
var rectangle = canvas.append("rect")
.attr("height", 500).attr("width", 100)
.attr("fill", "blue")
.attr("stroke", "blue")
.attr("stroke-width", 2);
var line = canvas.append("line")
.attr("x1", 500).attr("y1", 0)
.attr("x2", 500).attr("y2", 500)
.attr("stroke-width", 2)
.attr("stroke", "black");
</script>
</body>
</html>
如果您尝试放大或缩小上面渲染的 SVG,请注意图像质量不会受到影响。
二、助手
D3 附带了许多辅助函数,因此您不必加载Lodash或Underscore。
const data = [1, 2, 3, 4, 5];
const moreData = [[5, 20], [480, 90], [250, 50], [100, 33], [330, 95]];
d3.min(data); // 1
d3.max(moreData, function(d) { return d[0]; }); // 480
d3.max(moreData, function(d) { return d[1]; }); // 95
d3.extent(data); // [1, 5]
三、音阶
比例尺是任何可视化中至关重要的组成部分,D3 提供了多种比例尺(线性、对数、序数等)。D3 比例尺将数据空间(域)映射到像素空间(范围),并广泛用于绘制坐标轴。
回到我们的形状和辅助函数示例,如果我们想可视moreData化canvas元素的散点图,我们可以按如下方式声明比例尺。
var xScale = d3.scaleLinear()
.domain([0, d3.max(moreData, function(d) { return d[0]; })])
.range([0, 500])
var yScale = d3.scaleLinear()
.domain([0, d3.max(moreData, function(d) { return d[1]; })])
.range([500, 0]) // SVG is y-down
我们来测试一下我们的秤。
console.log(xScale(0)); // 0
console.log(xScale(480)); // 500
console.log(yScale(0)); // 0
console.log(yScale(95)); // 500
// The intermediate values are mapped linearly between 0 and 500.
要创建坐标轴,我们只需将比例尺传递给相应的坐标轴函数即可。
var xAxis = d3.axisBottom(xScale);
有关 D3 音阶的更多信息,请点击此处查看。
4. 在 D3 中创建散点图
现在我们准备创建第一个(或第一百个)散点图。首先,让我们创建一个div元素来包含我们的 SVG 图表。
<div id="plot"></div>
现在,让我们创建 SVG 元素。
var w = 500, h = 500, pad = 50; // defining width and height of the SVG element; and a little padding for the plot
var svg = d3.select("#plot") // Select the plot element from the DOM
.append("svg") // Append an SVG element to it
.attr("height", h)
.attr("width", w);
一些待绘制的数据。
// [x-coordinate, y-coordinate, radius]
const dataset = [[5, 20, 30], [480, 90, 20], [250, 50, 100], [100, 33, 40], [330, 85, 60]];
创建刻度和坐标轴。
// Scales
var xScale = d3.scaleLinear() // For the X axis
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([pad, w - pad]);
var yScale = d3.scaleLinear() // For the Y axis
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - pad, pad]);
var rScale = d3.scaleLinear() // Custom scale for the radii
.domain([0, d3.max(dataset, function(d) { return d[2]; })])
.range([1, 30]); // Custom range, change it to see the effects!
// Axes
var xAxis = d3.axisBottom(xScale); // handy axes for any orientation
var yAxis = d3.axisLeft(yScale);
绘制数据图。
var circ = svg.selectAll("circle") // Returns ALL matching elements
.data(dataset) // Bind data to DOM
.enter() // Add one circle per such data point
.append("circle")
.attr("cx", function(d) { return xScale(d[0]); })
.attr("cy", function(d) { return yScale(d[1]); })
.attr("r", function(d) { return rScale(d[2]); })
.attr("fill", "blue").attr("opacity", 0.5);
以上代码块包含了D3的关键部分。让我们来分析一下。
我们知道散点图本质上是一组圆。它们的位置和半径取决于dataset我们上面定义的参数。因此,我们希望每个数据点对应一个圆。D3 通过以下三个步骤实现此目标。
svg.selectAll("circle")返回所有匹配的元素,即使它们尚未创建。
.data(dataset)将上面的每个圆圈绑定到一个数据点(DOM - 数据绑定)。
.enter():为每个数据点添加一个圆圈。
太好了,现在让我们加上斧头来完成整个制作。
//X axis
svg.append("g") // Creates a group
.attr("class", "axis") // adding a CSS class for styling
.attr("transform", "translate(0," + (h - pad) + ")")
.call(xAxis);
//Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + pad +", 0)")
.call(yAxis);
上述变换是为了将坐标轴平移到原点。以下是完整的代码:
<!DOCTYPE html>
<html>
<head>
<title>Scatter Plot</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.axis {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<div id="plot"></div>
<script>
var dataset = [[5, 20, 30], [480, 90, 20], [250, 50, 100], [100, 33, 40], [330, 85, 60]];
var w = 500, h = 500, pad = 50;
var svg = d3.select("#plot")
.append("svg")
.attr("height", h)
.attr("width", w);
var xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([pad, w - pad]);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - pad, pad]);
var rScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) { return d[2]; })])
.range([1, 30]);
var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);
var circ = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) { return xScale(d[0]); })
.attr("cy", function(d) { return yScale(d[1]); })
.attr("r", function(d) { return rScale(d[2]); })
.attr("fill", "blue").attr("opacity", 0.5);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - pad) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + pad +", 0)")
.call(yAxis);
</script>
</body>
</html>
以及最终产品。
随着你向图表中添加更多点dataset,图表会自动反映出来。
此外
希望您喜欢这篇关于D3的简短介绍。以下是一些有用的资源:
- https://github.com/d3/d3/wiki/gallery
- https://bl.ocks.org/mbostock
- https://square.github.io/intro-to-d3/
最后,奉上一段精彩绝伦的《权力的游戏》可视化视频。
文章来源:https://dev.to/rxhl/getting-started-with-d3js-390


