折线图是数据统计中经常会用到的图表,用于二维数据的展示,本文将使用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');
复制代码

最终绘制的轴线图如下所示

查看完整示例代码