nvd3 multibarchart last bar is hidden not visible

依然范特西╮ 提交于 2020-01-06 05:08:23

问题


Based on this stackoverflow answer I was trying to copy essential parts to get proper scale for timeline. I use multibarcharts for multible graphs, from few records to hundreds with X-axis having data from 1930 to today.

I've copied it like this, but I have two issues:

  1. Last bar is always outside of graph
  2. bars overlap, which I can partly fix by altering numTicks, but isn't there a better way?

    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.js"></script>
    <script type="text/javascript">
        nv.addGraph(function() {
          var data = [{
            "values": [
    
                    { x: new Date("1999-12-01"), y: 42.27 } , 
    
                    { x: new Date("2000-12-01"), y: 41.73 } , 
    
                    { x: new Date("2001-12-01"), y: 41.34 } , 
    
                    { x: new Date("2002-12-01"), y: 41.84 } , 
    
                    { x: new Date("2003-12-01"), y: 43.93 } , 
    
                    { x: new Date("2004-12-01"), y: 42.18 } , 
    
                    { x: new Date("2005-12-01"), y: 42.31 } , 
    
                    { x: new Date("2006-12-01"), y: 43.14 } , 
    
                    { x: new Date("2007-12-01"), y: 43.24 } , 
    
                    { x: new Date("2008-12-01"), y: 39.30 } , 
    
                    { x: new Date("2009-12-01"), y: 43.80 } , 
    
                    { x: new Date("2010-12-01"), y: 44.10 } , 
    
                    { x: new Date("2011-12-01"), y: 54.10 } , 
    
                    { x: new Date("2012-12-01"), y: 62.10 } , 
    
                    { x: new Date("2013-12-01"), y: 56.70 } , 
    
                    { x: new Date("2014-12-01"), y: 45 } , 
    
                    { x: new Date("2015-12-01"), y: 55.60 } , 
    
                    { x: new Date("2026-12-01"), y: 54.40 } , 
    
                    { x: new Date("2027-12-01"), y: 57 } 
    
            ],
            "bar": true,
            "key": "Payout Ratio"
          }];
    
          var chart = nv.models.multiBarChart(),
              container = d3.select('#payout_ratio_chart svg'),
              availableWidth,
              numTicks = data[0].values.length,
              xScale = d3.time.scale();
    
          function updateAvailableWidth() {
              availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
          }
          updateAvailableWidth();
          nv.utils.windowResize(updateAvailableWidth);
    
          xScale.rangeBands = xScale.range;
          xScale.rangeBand = function() { return (1 - chart.groupSpacing()) * availableWidth / numTicks; };
    
          chart.multibar.xScale(xScale);
    
          var last_date = data[0].values[data[0].values.length-1].x;
          last_date.setMonth(last_date.getMonth() + 10);
          chart.xDomain([data[0].values[0].x, last_date]);
    
          chart.xAxis.tickFormat(function(d){ return d3.time.format('%b %Y')(new Date(d)); });
          chart.yAxis.tickFormat(d3.format(',f'));
    
    
          chart.showControls(false);
    
          container.datum(data).transition().duration(500).call(chart);
    
          nv.utils.windowResize(chart.update);
    
          return chart;
      });
    </script>
    

https://jsfiddle.net/lucas03/poamvfke/4/


回答1:


Checkout the code below which was derived from your posted code:

nv.addGraph(function() {
  var data = [{
    "values": [

      {
        x: new Date("1999-12-01"),
        y: 42.27
      },

      {
        x: new Date("2000-12-01"),
        y: 41.73
      },

      {
        x: new Date("2001-12-01"),
        y: 41.34
      },

      {
        x: new Date("2002-12-01"),
        y: 41.84
      },

      {
        x: new Date("2003-12-01"),
        y: 43.93
      },

      {
        x: new Date("2004-12-01"),
        y: 42.18
      },

      {
        x: new Date("2005-12-01"),
        y: 42.31
      },

      {
        x: new Date("2006-12-01"),
        y: 43.14
      },

      {
        x: new Date("2007-12-01"),
        y: 43.24
      },

      {
        x: new Date("2008-12-01"),
        y: 39.30
      },

      {
        x: new Date("2009-12-01"),
        y: 43.80
      },

      {
        x: new Date("2010-12-01"),
        y: 44.10
      },

      {
        x: new Date("2011-12-01"),
        y: 54.10
      },

      {
        x: new Date("2012-12-01"),
        y: 62.10
      },

      {
        x: new Date("2013-12-01"),
        y: 56.70
      },

      {
        x: new Date("2014-12-01"),
        y: 45
      },

      {
        x: new Date("2015-12-01"),
        y: 55.60
      },

      {
        x: new Date("2026-12-01"),
        y: 54.40
      },

      {
        x: new Date("2027-12-01"),
        y: 57
      }

    ],
    "bar": true,
    "key": "Payout Ratio"
  }];


  var fDate = data[0].values[0].x,
  lDate = new Date(data[0].values[data[0].values.length - 1].x);
  lDate.setFullYear(lDate.getFullYear() + 1);
  
  var chart = nv.models.multiBarChart()
    .showControls(false)
    .reduceXTicks(false)
    .rotateLabels(-45),
    container = d3.select('#payout_ratio_chart svg'),
    availableWidth,
    numTicks = (lDate.getFullYear() - fDate.getFullYear()) + 1,
    xScale = d3.time.scale();

  function updateAvailableWidth() {
    availableWidth = (chart.width() || parseInt(container.style('width')) || 960) - chart.margin().left - chart.margin().right;
  }
  updateAvailableWidth();

  xScale.rangeBands = xScale.range;
  xScale.rangeBand = function() {
    return (1 - chart.groupSpacing()) * availableWidth / numTicks;
  };

  chart.multibar.xScale(xScale);

  chart.xDomain([fDate, lDate]);

  chart.xAxis.tickFormat(function(d) {
    return d3.time.format('%b %Y')(new Date(d));
  });
  chart.yAxis.tickFormat(d3.format(',f'));

  container.datum(data).transition().duration(500).call(chart);

  nv.utils.windowResize(function() {
    updateAvailableWidth();
    chart.update();
  });

  return chart;
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.css" rel="stylesheet"/>
<div id="payout_ratio_chart">
  <svg style="width:100%;height:400px" />
</div>

<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.js"></script>

Fixes:

Only difference between your code and fixed code is how fDate, lDate and numTicks are calculated.

fDate is your start date while lDate is last date in data for the following year. Lastly, numTicks is difference between years in fDate and lDate.

Find jsfiddle here.




回答2:


You have a bar chart so you have to insert data points for not existing dates.

Here I have hard coded but you can write some logic to add missing dates. For some other data serie you can have values for the missing dates of this serie.

nvd3 draws these bars with a minimal height of 1px, so add a style to hide these small bars

.nvd3 .nv-groups rect[height="1"] {
    opacity: 0;
}

nv.addGraph(function() {
  var data = [{
    "values": [
      { x: new Date("1999-12-01"), y: 42.27 },
      { x: new Date("2000-12-01"), y: 41.73 },
      { x: new Date("2001-12-01"), y: 41.34 },
      { x: new Date("2002-12-01"), y: 41.84 },
      { x: new Date("2003-12-01"), y: 43.93 },
      { x: new Date("2004-12-01"), y: 42.18 },
      { x: new Date("2005-12-01"), y: 42.31 },
      { x: new Date("2006-12-01"), y: 43.14 },
      { x: new Date("2007-12-01"), y: 43.24 },
      { x: new Date("2008-12-01"), y: 39.30 },
      { x: new Date("2009-12-01"), y: 43.80 },
      { x: new Date("2010-12-01"), y: 44.10 },
      { x: new Date("2011-12-01"), y: 54.10 },
      { x: new Date("2012-12-01"), y: 62.10 },
      { x: new Date("2013-12-01"), y: 56.70 },
      { x: new Date("2014-12-01"), y: 45 },
      { x: new Date("2015-12-01"), y: 55.60 },
      { x: new Date("2016-12-01"), y: 0 },
      { x: new Date("2017-12-01"), y: 0 },
      { x: new Date("2018-12-01"), y: 0 },
      { x: new Date("2019-12-01"), y: 0 },
      { x: new Date("2020-12-01"), y: 0 },
      { x: new Date("2021-12-01"), y: 0 },
      { x: new Date("2022-12-01"), y: 0 },
      { x: new Date("2023-12-01"), y: 0 },
      { x: new Date("2024-12-01"), y: 0 },
      { x: new Date("2025-12-01"), y: 0 },
      { x: new Date("2026-12-01"), y: 54.40 },
      { x: new Date("2027-12-01"), y: 57 }
    ],
    "bar": true,
    "key": "Payout Ratio"
  }];

  var chart = nv.models.multiBarChart(),
    container = d3.select('#payout_ratio_chart svg');

  chart.xAxis.tickFormat(function(d) {
    return d3.time.format('%b %Y')(new Date(d));
  });
  chart.yAxis.tickFormat(d3.format(',f'));

  chart.showControls(false);

  container.datum(data).transition().duration(500).call(chart);

  nv.utils.windowResize(chart.update);

  return chart;
});
.nvd3 .nv-groups rect[height="1"] {
    opacity: 0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.css" rel="stylesheet"/>
<div id="payout_ratio_chart">
  <svg style="width:100%;height:400px" />
</div>

<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.js"></script>


来源:https://stackoverflow.com/questions/53575721/nvd3-multibarchart-last-bar-is-hidden-not-visible

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!