d3区域堆积折线图

时间:2019-08-21 20:23:41

标签: javascript d3.js

我正在修改以下堆积的折线图示例:https://bl.ocks.org/d3indepth/e4efd402b4d9fdb2088ccdf3135745c3

我要添加一个时间x轴,但是我在这段代码中苦苦挣扎:

var areaGenerator = d3.area()
  .x(function(d, i) {
      // return i * 100;
      return i * 253.5;
  })
  .y0(function(d) {
      return y(d[0]);
  })
  .y1(function(d) {
      return y(d[1]);
  });

原始示例的.x访问器为i * 100,这似乎是一个随机值。当我添加X轴时,堆积的折线图无法与日期刻度正确对齐。我可以通过返回i * 253.5来强制其排成一行,但这并不理想。我不太了解此区域功能的工作原理-希望能获得任何帮助。

let height = 600;
let width  = 800;
const yMax = 4000;
//var hEach  = 40;

let margin = {top: 20, right: 15, bottom: 25, left: 25};

width  =    width - margin.left - margin.right;
height =    height - margin.top - margin.bottom;

var svg = d3.select('body').append("svg")
  .attr("width",  width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

let formatDate = d3.timeFormat("%b-%Y")
let parseTime = d3.timeParse("%Y-%m-%d");


let data = [
  {
    "host_count": 2553,
    "container_count": 875,
    "hour": "2019-01-31",
    "apm_host_count": 0,
    "agent_host_count": 2208,
    "gcp_host_count": 0,
    "aws_host_count": 345
  },
  {
    "host_count": 1553,
    "container_count": 675,
    "hour": "2019-02-01",
    "apm_host_count": 0,
    "agent_host_count": 1208,
    "gcp_host_count": 0,
    "aws_host_count": 445
  },
  {
    "host_count": 716,
    "container_count": 6234,
    "hour": "2019-02-02",
    "apm_host_count": 0,
    "agent_host_count": 479,
    "gcp_host_count": 0,
    "aws_host_count": 237
  },
  {
    "host_count": 516,
    "container_count": 4234,
    "hour": "2019-02-03",
    "apm_host_count": 0,
    "agent_host_count": 679,
    "gcp_host_count": 0,
    "aws_host_count": 137
  }
];

  // format the data
  data.forEach(function(d) {
      d.hour = parseTime(d.hour);
  });

  // set the ranges
  var x = d3.scaleTime().range([0, width]);

  x.domain(d3.extent(data, function(d) { return d.hour; }));

  var xAxis = d3.axisBottom(x).ticks(11).tickFormat(d3.timeFormat("%y-%b-%d")).tickValues(data.map(d=>d.hour));


  var y = d3.scaleLinear()
    .domain([0, yMax])
    .range([height, 0]);

  var areaGenerator = d3.area()
  	.x(function(d, i) {
      console.log(d);
  		return i * 100;
  	})
  	.y0(function(d) {
  		return y(d[0]);
  	})
  	.y1(function(d) {
  		return y(d[1]);
  	});

  var colors = ['#FBB65B', '#513551', '#de3163']

  var stack = d3.stack()
    .keys(['agent_host_count', 'aws_host_count', 'container_count']);

  var stackedSeries = stack(data);

  d3.select('g')
  	.selectAll('path')
  	.data(stackedSeries)
  	.enter()
  	.append('path')
  	.style('fill', function(d, i) {
  		return colors[i];
  	})
  	.attr('d', areaGenerator)

  svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis);
<!doctype html>
<html lang="en">
  <head>
    <title>Usage</title>
  </head>
  <body>

    <div id="svg"></div>

    <script src="https://d3js.org/d3.v5.min.js"></script>

  </body>
</html>

1 个答案:

答案 0 :(得分:1)

在d3中使用轴时,实际上需要使用轴变量来计算比例因子。进行此计算的函数由scale*()方法返回。在您的代码中,x轴具有以下功能:

  var x = d3.scaleTime().range([0, width]);

这样,变量x现在包含一个将为您进行插值的函数。这就是您的areaGenerator函数的样子:

var areaGenerator = d3.area()
  .x(function(d, i) {
      return x(d.data.hour);
  })
  .y0(function(d) {
      return y(d[0]);
  })
  .y1(function(d) {
      return y(d[1]);
  });

您唯一需要记住的是,在计算值时,需要使用轴所基于的相同变量。即您的x轴是时间轴,因此您需要使用时间变量(d.data.hour)计算插值。

对于示例中100来自何处,您基本上是正确的。在该块中,值100或多或少是任意的。之所以选择它,是因为该图表在该比例下看起来相当不错。通过选择100,每个“刻度”之间的间隔为100像素,并且由于没有要判断的x轴,因此实际上只要使用每个数据点都可以更改,则实际上无关紧要。