D3 многострочный график отображает 2 линии, а не 3


В конечном счете, я просто пытаюсь построить узел.использование памяти js с течением времени, в простом многострочном графике. Может быть, есть пакет, который уже делает это, но я его не вижу. В узле есть 3 компонента.использование памяти js/V8, heapUsed, heapTotal, и rss, я хотел бы построить их со временем.

Чтобы сделать многострочный график С D3, я следую примеру здесь: https://code.tutsplus.com/tutorials/building-a-multi-line-chart-using-d3js--cms-22935

Полный код из пример здесь: https://github.com/jay3dec/MultiLineChart_D3/blob/master/index.html

Вот мой код:

<!DOCTYPE html>
<html lang='en'>

<head>

  <link href='http://getbootstrap.com/dist/css/bootstrap.min.css' rel='stylesheet'>
  <link href='http://getbootstrap.com/examples/justified-nav/justified-nav.css' rel='stylesheet'>
  <script src='http://d3js.org/d3.v3.min.js' charset='utf-8'></script>

  <style>

    .axis path {
      fill: none;
      stroke: #777;
      shape-rendering: crispEdges;
    }

    .axis text {
      font-family: Lato;
      font-size: 13px;
    }

  </style>

</head>

<body>

<div class='container'>

  <div class='jumbotron'>

    <svg id='visualisation' width='1000' height='500'></svg>

    <script>

      var heapTotal = [
        {x: Date.now() - 500, y: 100},
        {x: Date.now(), y: 125},
        {x: Date.now() + 500, y: 150},
      ];

      var heapUsed = [
        {x: Date.now() - 500, y: 110},
        {x: Date.now(), y: 111},
        {x: Date.now() + 500, y: 112},
      ];

      var rss = [
        {x: Date.now() - 500, y: 44},
        {x: Date.now(), y: 44},
        {x: Date.now() + 500, y: 44},
      ];

      const values = heapTotal.concat(heapUsed).concat(rss).reduce(function (prev, curr) {

        console.log('curr => ', curr);

        return {
          xMin: Math.min(prev.xMin, curr.x),
          xMax: Math.max(prev.xMax, curr.x),
          yMin: Math.min(prev.yMin, curr.y),
          yMax: Math.max(prev.yMax, curr.y),
        }

      }, {
        xMin: Number.MAX_SAFE_INTEGER,
        xMax: -1,
        yMin: Number.MAX_SAFE_INTEGER,
        yMax: -1
      });

      console.log('values => ', values);

      var vis = d3.select('#visualisation'),
        WIDTH = 1200,
        HEIGHT = 800,
        MARGINS = {
          top: 20,
          right: 20,
          bottom: 20,
          left: 50
        },
        xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([values.xMin, values.xMax]),
        yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([values.yMin, values.yMax]),
        xAxis = d3.svg.axis()
        .scale(xScale),
        yAxis = d3.svg.axis()
        .scale(yScale)
        .orient('left');

      vis.append('svg:g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
      .call(xAxis);

      vis.append('svg:g')
      .attr('class', 'y axis')
      .attr('transform', 'translate(' + (MARGINS.left) + ',0)')
      .call(yAxis);

      var lineGen = d3.svg.line()
      .x(function (d) {
        return xScale(d.x);
      })
      .y(function (d) {
        return yScale(d.y);
      })
      .interpolate('basis');

      vis.append('svg:path')
      .attr('d', lineGen(heapUsed))
      .attr('stroke', 'green')
      .attr('stroke-width', 2)
      .attr('fill', 'none');

      vis.append('svg:path')
      .attr('d', lineGen(heapTotal))
      .attr('stroke', 'blue')
      .attr('stroke-width', 2)
      .attr('fill', 'none');

      vis.append('svg:path')
      .attr('d', lineGen(rss))
      .attr('stroke', 'red')
      .attr('stroke-width', 2)
      .attr('fill', 'none');


    </script>
  </div>

</div>

</body>

</html>
Но по какой-то причине он строит только 2 строки, а не 3:

Введите описание изображения здесь

У кого-нибудь есть идеи, почему?

Похоже, что 3-я линия просто не видна, учитывая размеры-ака, ось y не опускается до 44.

Вот скриншот объекта values из кода:

Введите описание изображения здесь

1 2

1 ответ:

Проблема с вашим кодом заключается в том, что ваш выбор SVG (с именем vis) указывает на этот элемент SVG...

<svg id='visualisation' width='1000' height='500'></svg>

... который имеет высоту 500px.

Однако ваш вертикальный масштаб (yScale) использует переменную HEIGHT, которая является 800.

Поэтому ось правильная, но она идет за нижнюю границу SVG (вы можете ясно видеть, что осматриваете элемент), а также вашу третью линию, которая окрашивается, но она не видна, потому что она в настоящее время лежит вне пределов SVG.

Решение : используйте переменные HEIGHT и WIDTH для задания высоты и ширины вашего SVG:

vis.attr("width", WIDTH)
    .attr("height", HEIGHT)

Альтернативно, если высота, которую вы хотите, на самом деле является встроенной высотой этого SVG (то есть 500), измените свою переменную HEIGHT соответственно.

Вот ваш обновленный код, теперь вы можете увидеть последнюю строку:

var heapTotal = [{
   x: Date.now() - 500,
   y: 100
 }, {
   x: Date.now(),
   y: 125
 }, {
   x: Date.now() + 500,
   y: 150
 }, ];

 var heapUsed = [{
   x: Date.now() - 500,
   y: 110
 }, {
   x: Date.now(),
   y: 111
 }, {
   x: Date.now() + 500,
   y: 112
 }, ];

 var rss = [{
   x: Date.now() - 500,
   y: 44
 }, {
   x: Date.now(),
   y: 44
 }, {
   x: Date.now() + 500,
   y: 44
 }, ];

 const values = heapTotal.concat(heapUsed).concat(rss).reduce(function(prev, curr) {


   return {
     xMin: Math.min(prev.xMin, curr.x),
     xMax: Math.max(prev.xMax, curr.x),
     yMin: Math.min(prev.yMin, curr.y),
     yMax: Math.max(prev.yMax, curr.y),
   }

 }, {
   xMin: Number.MAX_SAFE_INTEGER,
   xMax: -1,
   yMin: Number.MAX_SAFE_INTEGER,
   yMax: -1
 });


 var vis = d3.select('#visualisation'),
   WIDTH = 1200,
   HEIGHT = 800,
   MARGINS = {
     top: 20,
     right: 20,
     bottom: 20,
     left: 50
   },
   xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([values.xMin, values.xMax]),
   yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([0.95*values.yMin, values.yMax]),
   xAxis = d3.svg.axis()
   .scale(xScale),
   yAxis = d3.svg.axis()
   .scale(yScale)
   .orient('left');

 vis.attr("width", WIDTH)
   .attr("height", HEIGHT)

 vis.append('svg:g')
   .attr('class', 'x axis')
   .attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
   .call(xAxis);

 vis.append('svg:g')
   .attr('class', 'y axis')
   .attr('transform', 'translate(' + (MARGINS.left) + ',0)')
   .call(yAxis);

 var lineGen = d3.svg.line()
   .x(function(d) {
     return xScale(d.x);
   })
   .y(function(d) {
     return yScale(d.y);
   })
   .interpolate('basis');

 vis.append('svg:path')
   .attr('d', lineGen(heapUsed))
   .attr('stroke', 'green')
   .attr('stroke-width', 2)
   .attr('fill', 'none');

 vis.append('svg:path')
   .attr('d', lineGen(heapTotal))
   .attr('stroke', 'blue')
   .attr('stroke-width', 2)
   .attr('fill', 'none');

 vis.append('svg:path')
   .attr('d', lineGen(rss))
   .attr('stroke', 'red')
   .attr('stroke-width', 2)
   .attr('fill', 'none');
.axis path {
  fill: none;
  stroke: #777;
  shape-rendering: crispEdges;
}

.axis text {
  font-family: Lato;
  font-size: 13px;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<svg id='visualisation'></svg>

PS: Я немного уменьшил нижний конец вашей шкалы (0.95*values.yMin), поэтому последняя строка не остается на вершине оси.