折线图是数据统计中经常会用到的图表,用于二维数据的展示,本文将使用D3上手制作一个简单的折线图
确定数据
表格数据是一家店铺一年的销售量
月份 | 销售量(件) |
---|---|
1月 | 454 |
2月 | 628 |
3月 | 756 |
4月 | 632 |
5月 | 582 |
6月 | 704 |
7月 | 766 |
8月 | 804 |
9月 | 884 |
10月 | 960 |
11月 | 1095 |
12月 | 1250 |
var dataset = [[1, 224], [2, 528], [3, 756], [4, 632], [5, 582], [6, 704],
[7, 766], [8, 804], [9, 884], [10, 960], [11, 1095], [12, 1250]];
复制代码
要找出最大值和最小值,需要用到D3的数组方法
- d3.min(array[,accessor]) 返回数组中的最小值
- d3.max(array[,accessor]) 返回数组中的最大值
accessor是一个执行min或max函数前调用的方法,因为dataset是一个二维数组,因此需要在每一项数组拿出来后返回子数组中的第二个数值,可以取得1至12月份销售量的最大值和最小值
var min = d3.min(dataset, function(d) {
return d[1];
})
var max = d3.max(dataset, function(d) {
return d[1];
})
复制代码
还需要一些画图的基础数据
// 图表的宽度和高度
var width = 600;
var height = 600;
// 预留给轴线的距离
var padding = { top: 50, right: 50, bottom: 50, left: 50 };
复制代码
设置比例尺
由于画布的大小有限,数据值很大,所以折线图通常要用到线性比例尺,用画布上的距离来代表图表中量化的数值
- d3.scaleLinear() 设置一个线性比例尺
- quantize.domain([domain]) 取得或设置比例尺的定义域
- quantize.range([range]) 取得或设置比例尺的值域
在x轴方向,数据从1月份到12月份,画布上的对应距离为画布宽度减去左右空隙,在y轴方向同理,不过y轴的值域是颠倒的,因为y轴的零点在最下面,刻度从下往上的递增
var xScale = d3.scaleLinear()
.domain([1, 12])
.range([0, width - padding.left - padding.right]);
var yScale = d3.scaleLinear()
.domain([0, max])
.range([height - padding.top - padding.bottom, 0]);
复制代码
绘制轴线
- d3.axisBottom(scale) 创建一个新的轴生成器
- d3.axisBottom(scale).scale([scale]) 设置或者取得比例尺
有了比例尺就可以绘制轴线了,创建比例尺,并调用刚才设置的比例尺
var svg = d3.select('body')
.append('svg')
.attr('width', width + 'px')
.attr('height', height + 'px');
var xAxis = d3.axisBottom()
.scale(xScale);
var yAxis = d3.axisLeft()
.scale(yScale);
复制代码
在svg中需要一个容器来装轴线,就是装载群组的g标签,在g标签中调用轴生成器,生成例如path、line、text等svg标签组成的轴线
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(' + padding.left + ',' + (height - padding.bottom) + ')')
.call(xAxis);
svg.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
.call(yAxis);
复制代码
绘制的轴线图如下所示
绘制曲线
- d3.line() 新建一个线生成器
- line.x([x]) 设置或获取x-坐标访问器
- line.y([y]) 设置或获取y-坐标访问器
D3为了生成各种线段、形状、图形,内置了路径生成器,这里需要用到线段生成器,并指定二维的访问器,调用刚才设置的比例尺
var linePath = d3.line()
.x(function(d){ return xScale(d[0]) })
.y(function(d){ return yScale(d[1]) });
复制代码
svg.append('g')
.append('path')
.attr('class', 'line-path')
.attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
.attr('d', linePath(dataset))
.attr('fill', 'none')
.attr('stroke-width', 3)
.attr('stroke', 'green');
复制代码
svg.append('g')
.selectAll('circle')
.data(dataset)
.enter()
.append('circle')
.attr('r', 5)
.attr('transform', function(d){
return 'translate(' + (xScale(d[0]) + padding.left) + ',' + (yScale(d[1]) + padding.top) + ')'
})
.attr('fill', 'green');
复制代码
最终绘制的轴线图如下所示