2

Following the question NVD3 Line chart tics wrongly aligned to grid when using datetype on xAxis:

In short:

The problem I have encountered now is that my data is wrongly aligned with the Axis

The Problem

When I have no data for one day (or more) the graph "save" a place for the missing day. I want to avoid it.

enter image description here

I know that I can add the missing day's data with 0s but my question is if I can do this without it.

var app = angular.module('plunker', ['nvd3']);

app.controller('MainCtrl', function($scope) {
  $scope.options = {
    chart: {
      type: 'lineChart',
      height: 500,
      useInteractiveGuideline: true,
      xAxis: {
        tickFormat: function(d) {
          return d3.time.format('%H %d/%m')(new Date(d));
        },
        rotateLabels: -45,
        tickValues: function(values) {
          var a =  _.map(values[0].values, function(v) {
            return new Date(v.x);
          });
          return a;
        }
      }
    }
  };


  $scope.data = [
    // date, series1, series2, series
    [1446418800000, 2, 2, 1],
    [1446505200000, 0, 0, 0],
    [1446591600000, 14, 12, 2],
    [1446678000000, 65, 38, 27],
    [1446764400000, 11, 6, 5],
    // [1446850800000, 0, 0, 0],
    // [1446937200000, 0, 0, 0],
    [1447023600000, 6, 4, 2],
    [1447110000000, 0, 0, 0],
    [1447196400000, 0, 0, 0],
    [1447282800000, 0, 0, 0],
    [1447369200000, 12, 2, 10],
    [1447455600000, 0, 0, 0],
    [1447542000000, 0, 0, 0],
    [1447628400000, 0, 0, 0],
    [1447714800000, 1, 0, 1]
  ];

  var graphData = function(data, labels, colors) {
    var series = [];

    // first(0) value is date
    for (var i = 1; i < data[0].length; i++) {
      var values = [];
      for (var j = 0; j < data.length; j++) {
        values.push({
          x: data[j][0], // x is date
          y: data[j][i] // y is value
        });
      }
      series.push({
        values: values, // graph data
        key: labels[i - 1], // the label
        color: colors[i - 1] // color of series
      });
    }
    return series;
  };

  $scope.graphData = graphData($scope.data, ['One', 'Two', 'Three'], ['#6C6C6C', '#2ca02c', '#E43211']);
});
<!DOCTYPE html>
<html ng-app="plunker">
  <head>
    <meta charset="utf-8" />
    <title>Angular-nvD3 Line Chart</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.css"/>    
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
    <script src="https://cdn.rawgit.com/novus/nvd3/master/build/nv.d3.js"></script>
    <script src="https://rawgit.com/krispo/angular-nvd3/v1.0.3/dist/angular-nvd3.js"></script>
    <script data-require="lodash.js@1.3.1" data-semver="1.3.1" src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.1/lodash.min.js"></script>
  </head>
  <body ng-controller="MainCtrl">
    <nvd3 options="options" data="graphData" class="with-3d-shadow with-transitions"></nvd3>
  </body>
</html>

http://plnkr.co/edit/42uzlu4AjnHJpI7o41l3?p=preview

Community
  • 1
  • 1
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135

2 Answers2

1

Thanks to @krispo on github here is the answer:

var app = angular.module('plunker', ['nvd3']);

app.controller('MainCtrl', function($scope) {
  $scope.options = {
    chart: {
      type: 'lineChart',
      height: 500,
      useInteractiveGuideline: true,
      x: function(d){ return d.i},
      xAxis: {
        tickFormat: function(d) {
          var data = $scope.graphData[0].values[d].x;
          return d3.time.format('%H %d/%m')(new Date(data));
        },
        rotateLabels: -45,
        tickValues: function(values) {
          var a =  _.map(values[0].values, function(v,i) {
            return i
          });
          return a;
        },
        showMaxMin: false
      }
    }
  };


  $scope.data = [
    // date, series1, series2, series
    [1446418800000, 2, 2, 1],
    [1446505200000, 0, 0, 0],
    [1446591600000, 14, 12, 2],
    [1446678000000, 65, 38, 27],
    [1446764400000, 11, 6, 5],
    // [1446850800000, 0, 0, 0],
    // [1446937200000, 0, 0, 0],
    [1447023600000, 6, 4, 2],
    [1447110000000, 0, 0, 0],
    [1447196400000, 0, 0, 0],
    [1447282800000, 0, 0, 0],
    [1447369200000, 12, 2, 10],
    [1447455600000, 0, 0, 0],
    [1447542000000, 0, 0, 0],
    [1447628400000, 0, 0, 0],
    [1447714800000, 1, 0, 1]
  ];

  var graphData = function(data, labels, colors) {
    var series = [];

    // first(0) value is date
    for (var i = 1; i < data[0].length; i++) {
      var values = [];
      for (var j = 0; j < data.length; j++) {
        values.push({
          i: j,
          x: data[j][0], // x is date
          y: data[j][i] // y is value
        });
      }
      series.push({
        values: values, // graph data
        key: labels[i - 1], // the label
        color: colors[i - 1] // color of series
      });
    }
    return series;
  };

  $scope.graphData = graphData($scope.data, ['One', 'Two', 'Three'], ['#6C6C6C', '#2ca02c', '#E43211']);
  console.log($scope.graphData);

});
<!DOCTYPE html>
<html ng-app="plunker">
  <head>
    <meta charset="utf-8" />
    <title>Angular-nvD3 Line Chart</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.css"/>    

    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
    <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.1/nv.d3.min.js"></script> -->
    <script src="https://cdn.rawgit.com/novus/nvd3/master/build/nv.d3.js"></script>
    <script src="https://rawgit.com/krispo/angular-nvd3/v1.0.3/dist/angular-nvd3.js"></script>
    <script data-require="lodash.js@1.3.1" data-semver="1.3.1" src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.3.1/lodash.min.js"></script>

    <!--<script src="app.js"></script>-->
  </head>
  <body ng-controller="MainCtrl">
    <nvd3 options="options" data="graphData" class="with-3d-shadow with-transitions"></nvd3>
  </body>
</html>

plnkr

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
0

I am afraid I do not have a complete answer here, but since you follow my answer from the previous question, I will describe the consequences.

The problem occurs because you provide the tickValues on your own. If you delete the custom function the axis will use it's default function and produce a (let's call it) evenly distributed ticks: default function ticks

Therefore, the place you should fix is the tickValues function. In my opinion, adding logic to it, so it would produce evenly distributed ticks would be quite hacky, but not impossible (and I could think of couple ways to do it). But still (imo) in this situation it would be best to do it on the server side.

Good luck!

Atais
  • 10,857
  • 6
  • 71
  • 111