javascript - D3 多线图显示 2 条线而不是 3 条线

标签 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

最佳答案

您的代码的问题在于您的 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),所以最后一行不会留在轴的顶部。

关于javascript - D3 多线图显示 2 条线而不是 3 条线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45406986/

相关文章:

Javascript 和 Jquery : Adding markers for Google Maps when clicking a button

javascript - 在 CKEditor 中,无法上传图像。?

javascript - 在 ESlint 配置中包含像 D3js 这样的自定义库?

javascript - d3.json() 和 JSON.parse() 产生相同的结果吗?

javascript - Node.js - 不使用 FS lib 附加 JSON 文件 - require('fs)

javascript - 读取 Javascript 对象

html - safari margin top 不同于 chrome 和 firefox

html - 是否可以选择没有特定类型子元素的元素?

javascript - 导航在浏览器调整大小时位于内容下方

javascript - D3.js Bilevel Partition - 初始图表加载切片放大