上一篇文章我们讲了【d3.js入门】基本面积图动画,这篇文章我们基于简单的面积图来开发一个有趣的小案例。
实现思路:
- 绘制面积图图
- 绘制很多面积图
- 让面积图高低有层级感
- 让面积图填充渐变色
- 层级不同颜色有变化
- 让面积图躁动起来
哦,这个案例在B站有视频讲解,有兴趣的jy可以移步观看:【可视化100天-4】层峦叠嶂山水画 www.bilibili.com/video/BV1wK…
下面是主要的绘制函数。接下来我将对其代码进行解释。
private drawArea(data, colors, vmax) {
data.map((d, i) => {
d.id = i;
})
这里定义了一个私有函数drawArea
,它接受三个参数:data
、colors
和vmax
。首先,我们使用map
方法遍历数据数组,并将每个元素的索引赋值给id
属性。
const gline = this.backg.selectAll('g').filter('.areag')
.data(data)
.join("g")
.attr('class', 'areag')
接下来,我们定义一个选择集gline
,并使用filter
方法选择具有.areag
类的g
元素。对于每个数据元素,我们使用join
方法创建一个g
元素,并将其class
属性设置为areag
。
let gwmax = this.domdiv.offsetWidth
let ghmax = this.domdiv.offsetHeight
data.map(d => {
const data = d.data;
let scale = d3.scaleLinear()
.domain([0, vmax])
.rangeRound([ghmax, 0])//y轴
let scale2 = d3.scaleLinear()
.domain([0, data.length - 1])
.rangeRound([0, gwmax]) // x轴
const arr = [];
data.map((e, i) => {
arr.push([scale(e), scale2(i)])
})
d.sdata = arr;
})
然后,我们定义了gwmax
和ghmax
变量,分别表示绘图区域的宽度和高度。接下来,我们遍历数据数组,并为每个数据元素创建一个比例尺。这里,我们使用scaleLinear
方法创建了一个线性比例尺,它的定义域为[0, vmax]
,值域为[ghmax, 0]
。这个比例尺用于将数据映射到y轴。我们还创建了一个线性比例尺,它的定义域为[0, data.length - 1]
,值域为[0, gwmax]
。这个比例尺用于将数据映射到x轴。
接下来,我们创建一个空数组arr
,并使用map
方法遍历数据数组。对于每个数据元素,我们将其转换为一个二元数组,其中第一个元素是其在y轴上的坐标值,第二个元素是其在x轴上的坐标值。将这些二元数组添加到arr
数组中。最后,我们为每个数据元素添加sdata
属性,并将其设置为arr
数组。
const area = d3.area()
.curve(d3.curveMonotoneX)
.x((d, i) => { return d[1] })
.y1((d) => { return d[0] })
.y0(ghmax);
gline.selectAll('path').filter('.area')
.data(d => [d])
.join('path')
.attr('class', 'area')
.attr('fill', d => `url(#linearA${d.id}${this.__id})`)
.attr('d', d => {
return area(d.sdata)
})
}
最后,我们定义了一个area
对象,它表示一个区域生成器。我们使用curve
方法设置了曲线插值方式,并分别使用x
、y1
和y0
方法设置了该区域的x、y坐标值。然后,我们选择所有.area
类的path
元素,并使用join
方法创建path
元素。我们为每个path
元素设置class
属性为area
,并将其fill
属性设置为一个线性渐变。最后,我们使用sdata
属性中存储的数据来设置d
属性,该属性表示该区域的路径。