内容出自:FreeCodeCamp
D3 或 D3.js 表示数据驱动文档。它是一个用于在浏览器中创建动态和交互式数据视觉化的 JavaScript 库。1
学习资源
- D3.js - Data-Driven Documents
- Data Visualization with D3 – Full Course for Beginners [2022] - YouTube
- The D3 Graph Gallery – Simple charts made with d3.js
- Introduction to D3.js | D3 in Depth
- 数据可视化 认证 | freeCodeCamp.org
- Amelia Wattenberger
- GitHub - xswei/d3js_doc: D3js 中文文档 D3 中文
基础操作
修改元素
select()
:- 功能:从文档中选择一个元素。
- 参数:它接受你想要选择的元素的名字作为参数,并返回文档中第一个与名字匹配的 HTML 节点。
selectAll()
- 选择一组元素。 并以 HTML 节点数组的形式返回该文本中所有匹配所输入字符串的对象
append()
- 功能:将 HTML 节点附加到选定项目,并返回该节点的句柄。
- 参数:接收你希望添加到文档中的元素
text()
- 功能:设置所选节点的文本,也可以获取当前文本。 也可以用来添加标签
- 参数:字符串或者回调函数
js
const anchor = d3.select('a')
在 D3 中可以串联多个方法,连续执行一系列操作。->[[function chaining|链式调用]]
使用数据
data()
:- 将元素与数据绑定
- 不需要写 for 循环或者用 forEach() 迭代数据集中的对象。 data() 方法会解析数据集,任何链接在 data() 后面的方法都会为数据集中的每个对象运行一次。
- 可以使用方括号的方式,如
d[0]
,来访问数组中的值。
enter()
:获取需要插入的选择集(数据个数大于元素个数)的占位符.
当 enter() 和 data() 方法一起使用时,它把从页面中选择的元素和数据集中的元素作比较。 如果页面中选择的元素较少则创建缺少的元素。
可以理解为管理仓库的,选择的元素是货架,数据是货,如果货架不够了,就再补几个货架,如果多了就不管
html
<body><ul></ul><script>const dataset = ['a', 'b', 'c']d3.select('ul').selectAll('li').data(dataset).enter().append('li').text('New item')</script></body>
使用动态数据
text 中设置回调处理数据如:
d3.json()
: 从指定的 input URL 获取 JSON 文件。如果指定了 init 则会将其传递给底层的 fetch 方法
html
<body><script>const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9]d3.select('body').selectAll('h2').data(dataset).enter().append('h2').text(d => d + ' USD')</script></body>
给元素添加内联样式
style()
- 功能:在动态元素上添加内联 CSS 样式
- 参数:以用逗号分隔的键值对作为参数
js
selection.style('color', 'blue')//用回调过滤selection.style('color', d => {return d < 20 ? 'red' : 'green'})// 动态设置样式selection.style('height', d => d + 'px') // 动态设置高度
添加 Class
attr()
- 功能:可以给元素添加任何 HTML 属性,包括 class 名称。
- 参数:
- attr() 方法和 style() 的使用方法一样。 它使用逗号分隔值,并且可以使用回调函数
- 可接收一个回调函数来动态设置属性。 这个回调函数有两个参数,一个是数据点本身(通常是
d
),另一个是该数据点在数组中的下标 i, 这个参数是可选的
- 当需要添加 class 时,class 参数保持不变,只有 container 参数会发生变化。
js
selection.attr('class', 'container')// 回调selection.attr('property', (d, i) => {})// 比如改变间距svg.selectAll('rect').data(dataset).enter().append('rect').attr('x', (d, i) => {return i * 30 //改变间距}).attr('y', (d, i) => {return d * 3 //改变高度})//悬停效果.attr('class', 'bar')
标签
- 和 rect 元素类似,text 元素也需要 x 和 y 属性来指定其放置在 SVG 画布上的位置, 它也需要能够获取数据来显示数据值。
- 标签样式
fill
属性为 text 节点设置文本颜色style()
方法设置其它样式的 CSS 规则,例如 font-family 或 font-size。
js
//添加标签svg.selectAll('text').data(dataset).enter().append('text').attr('x', (d, i) => i * 30).attr('y', (d, i) => h - 3 * d - 3) // 高三个单位是减.text(d => d)// 添加样式.attr('fill', 'red').style('font-size', '25px')//悬停效果.attr('class', 'bar')/** css中.bar:hover {fill: brown;}**/
添加工具提示 tooltip
- 当用户在一个对象上悬停时,提示框可以显示关于这个对象更多的信息
- title
js
svg.selectAll('rect').data(dataset).enter().append('rect').attr('x', (d, i) => i * 30).attr('y', (d, i) => h - 3 * d).attr('width', 25).attr('height', (d, i) => d * 3)// 每个 rect 节点下附加 title 元素。 然后用回调函数调用 text() 方法使它的文本显示数据值。.append('title').text(d => d)
SVG
- 坐标系:坐标轴的原点在左上角。 x 坐标为 0 将图形放在 SVG 区域的左边缘, y 坐标为 0 将图形放在 SVG 区域的上边缘。 x 值增大矩形将向右移动, y 值增大矩形将向下移动。
创建 SVG
js
//创建svgselection.append('svg')
反转 SVG 元素
- 为了使条形图向上,需要改变 y 坐标计算的方式
SVG 区域的高度为 100。 如果在集合中一个数据点的值为 0,那么条形将从 SVG 区域的最底端开始(而不是顶端)。 为此,y 坐标的值应为 100。 如果数据点的值为 1,你将从 y 坐标为 100 开始来将这个条形设置在底端, 然后需要考虑该条形的高度为 1,所以最终的 y 坐标将是 99。
(高度从下面开始计算,坐标轴从上面开始)
- y 坐标为
y = heightOfSVG - heightOfBar
会将条形图向上放置。 - 通常,关系是
y = h - m * d
,其中 m 是缩放数据点的常数。
更改 SVG 元素的颜色
- 在 SVG 中, rect 图形用
fill
属性着色。 它支持十六进制代码、颜色名称、rgb 值以及更复杂的选项,比如渐变和透明。
js
svg.selectAll('rect').data(dataset).enter().append('rect').attr('x', (d, i) => i * 30).attr('y', (d, i) => h - 3 * d).attr('width', 25).attr('height', (d, i) => 3 * d)//将所有条形图的 fill 设置为海军蓝。.attr('fill', 'navy')
SVG 图形
- SVG 支持多种图形,比如矩形和圆形, 并用它们来显示数据。
矩形
SVG 的 rect 有四个属性。 x 和 y 坐标指定图形放在 svg 区域的位置, height 和 width 指定图形大小
js
const svg = d3.select('body').append('svg').attr('width', w).attr('height', h).append('rect') //rect矩形.attr('width', 25).attr('height', 100).attr('x', 0).attr('y', 0)
圆形
- SVG 用 circle 标签来创建圆形
- circle 有三个主要的属性。
- cx 和 cy 属性是坐标。 它们告诉 D3 将图形的中心放在 SVG 画布的何处。
- 半径( r 属性)给出 circle 的大小。
- 和 rect 的 y 坐标一样,circle 的 cy 属性是从 SVG 画布的顶端开始测量的,而不是从底端。
js
svg.selectAll('circle').data(dataset).enter().append('circle')//散点图.attr('cx', d => d[0]).attr('cy', d => h - d[1]).attr('r', '5')
比例尺
创建线性比例
条形图和散点图都直接在 SVG 画布上绘制数据。 但是,如果一组的高或者其中一个数据点比 SVG 的高或宽更大,它将跑到 SVG 区域外。
D3 中,比例尺可帮助布局数据。 scales 是函数,它告诉程序如何将一组原始数据点映射到 SVG 画布上。
线性缩放
- 通常使用于定量数据
- 默认情况下,比例尺使用一对一关系(identity relationship)。 输入的值和输出的值相同。
js
const scale = d3.scaleLinear()
例子
js
const scale = d3.scaleLinear() // 在这里创建轴const output = scale(50) // 调用 scale,传入一个参数d3.select('body').append('h2').text(output)
按比例设置域和范围
- 域 domain:假设有一个数据集范围为 50 到 480, 这是缩放的输入信息,也被称为域。
- 范围 range:沿着 x 轴将这些点映射到 SVG 画布上,位置介于 10 个单位到 500 个单位之间。 这是输出信息,也被称为范围。
domain()
和range()
方法设置比例尺的值, 它们都接受一个至少有两个元素的数组作为参数。domain()
方法给比例尺传递关于散点图原数据值的信息range()
方法给出在页面上进行可视化的实际空间信息
例子:
js
scale.domain([50, 480]); //域scale.range([10, 500]); //范围scale(50) //10scale(480) //500scale(325) //323.37scale(750)。// 807.。67d3.scaleLinear()
按顺序,将在控制台中显示以下值:10、500、323.37 和 807.67。
注意,比例尺使用了域和范围之间的线性关系来找出给定数字的输出值。 域中的最小值(50)映射为范围中的最小值(10)。
(也就是给定范围,用线性关系缩小,比如图片放大缩小,给了原图大小和缩小后的图片大小,根据线性关系比例来计算每个像素的位置,元素的大小)
最小值最大值
d3.min
:最小值d3.max
: 最大值min()
和max()
都可以使用回调函数,下面例子中回调函数的参数 d 是当前的内部数组。min()
和max()
方法在设置比例尺时十分有用
例子:找到二维数组的最大值和最小值
js
const locationData = [[1, 7],[6, 3],[8, 3]]const minX = d3.min(locationData, d => d[0]) //查找在d[0]位置上最小的值
使用动态比例
- 用
min()
和max()
来确定比例尺范围和域 padding
将在散点图和 SVG 画布边缘之间添加空隙。- 保持绘图在右上角。 当为 y 坐标设置 range 时,大的值(height 减去 padding)是第一个参数,小的值是第二个参数。
js
const dataset = [[34, 78],[109, 280],[310, 120],[79, 411],[420, 220],[233, 145],[333, 96],[222, 333],[78, 320],[21, 123]]const w = 500const h = 500const padding = 30const xScale = d3.scaleLinear().domain([0, d3.max(dataset, d => d[0])]).range([padding, w - padding])
使用预定义的比例放置元素
- 用比例尺函数为 SVG 图形设置坐标属性值。
- 当显示实际数据值时,不用使用比例尺,例如,在提示框或标签中的
text()
方法。
js
svg.selectAll('circle').data(dataset).enter().append('circle').attr('cx', d => xScale(d[0])).attr('cy', d => yScale(d[1])).attr('r', '5')
添加坐标轴
- 位置:
axisLeft()
和axisBottom()
。 - g 元素, g 是英文中组(group)的缩写,在渲染时,轴只是一条直线。 因为它是一个简单的图形,所以可以用 g
- SVG 支持多种 transforms,但是定位轴需要使用 translate 属性
例子:
js
// X轴const xAxis = d3.axisBottom(xScale)svg.append('g').attr('transform', 'translate(0, ' + (h - padding) + ')') // translate(0,x).call(xAxis) // x轴作为参数被传递给 call() 方法// Y轴const yAxis = d3.axisLeft(yScale)svg.append('g').attr('transform', 'translate(0,' + (h - padding) + ')').call(xAxis)svg.append('g').attr('transform', 'translate(' + padding + ',0)').call(yAxis)
常见图表
散点图
圆圈来映射数据点,每个数据点有两个值。 这两个值和 x 和 y 轴相关联,在可视化中用来给圆圈定位。
js
svg.selectAll('circle').data(dataset).enter().append('circle').attr('cx', d => d[0])//反转图像.attr('cy', d => h - d[1]).attr('r', '5')// 散点图加标签svg.selectAll('text').data(dataset).enter().append('text')// Add your code below this line.attr('x', d => d[0] + 5).attr('y', d => h - d[1]).text(d => d[0] + ', ' + d[1])