D3多线图显示2行而不是3行

时间:2017-07-31 03:17:49

标签: javascript html d3.js svg

最后,我只想在一个简单的多线图中绘制Node.js内存使用情况。也许有一个包已经做到了,但我没有看到一个。 Node.js / V8内存使用有3个组件,heapUsedheapTotalrss,我想随着时间的推移绘制它们。

要使用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行:

enter image description here

任何人都知道为什么?

考虑到尺寸,似乎第3条线是不可见的 - 也就是说,y轴不会下降到44.

以下是代码中值对象的屏幕截图:

enter image description here

1 个答案:

答案 0 :(得分:1)

您的代码存在的问题是您的SVG选择(名为vis)指向此SVG元素...

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

......高度为500px。

但是,您的垂直比例(yScale)使用HEIGHT变量,即800

因此,轴是正确的,但它超出 SVG的下限(你可以清楚地看到检查元素),以及正在绘制的第三行,但它不可见,因为它目前不在SVG限制之内。

解决方案:使用HEIGHTWIDTH变量设置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),所以最后一行不会停留在轴的顶部。