Search code examples
javascriptchartsgoogle-visualizationlinechart

Google line chart month label in hAxis not correct


I have an animated line chart with 3 lines.

Fiddle:

https://jsfiddle.net/8b3czfuq/

I'm displaying daily wise data on a line chart with month-year label in h-axis.

google.charts.load('current', {
  packages: ['corechart']
});
google.setOnLoadCallback(prepareChartData);

function prepareChartData(){
  var chartData = new google.visualization.DataTable();
  chartData.addColumn('date', 'Date');
  chartData.addColumn('number', 'Total');
  chartData.addColumn('number', 'Dogs');
  chartData.addColumn('number', 'Cats');
  title = 'My Chart';

  var options = {
    title: title,
    curveType: 'function',
    legend: {position: 'bottom', alignment: 'start'},
    colors: ['#003f5c', '#ffa600', '#665191', '#f95d6a'],

    annotations: {
      alwaysOutside: true,
      textStyle: {
        color: 'black',
        fontSize: 11
      },
    },
    hAxis: {
      format: 'MMM yy',
      viewWindowMode: "explicit",
    },
    vAxis: {
      minValue: 0,
      viewWindowMode: "explicit",
      viewWindow: { min: 0 },
      title: ''
    },
    titleTextStyle: {
      color:'#3a3a3a',
      fontSize:24,
      bold:false
      // fontName: "Segoe UI"
      },
    bar: {groupWidth: '95%'},
    bars: 'horizontal'
  };

  var chartDivId = "chart_div";
  var chart = new google.visualization.LineChart(document.getElementById(chartDivId));
  var rawData =[];

   var chart_object = { "Feb 20": {monthLabel: "Feb", chartArray:[{'date': "2020-2-12", 'total': "5", 'cats': "10", 'dogs': "10"},{'date': "2020-2-13", 'total': "15", 'cats': "20", 'dogs': "20"}]}, "Mar 20": {monthLabel: "Mar", chartArray:[{'date': "2020-3-10", 'total': "5", 'cats': "10", 'dogs': "10"},{'date': "2020-03-11", 'total': "15", 'cats': "30", 'dogs': "30"}]}};

  $.each(chart_object, function(i, chartobject) {
 	$.each(  chartobject.chartArray, function( chartIndex , chartValue ){

    date = chartValue['date'];
    total = parseInt(chartValue['total']);
    catscount = parseInt(chartValue['cats']);
    dogscount = parseInt(chartValue['dogs']);
    catspercentage = 0;
    catspercentageAnnotation = catscount+",  percent "+catspercentage+"%";
    dogsspercentage = 0;
    dogsspercentageAnnotation = dogscount+",  percent "+dogsspercentage+"%";

    rawData.push([ new Date(date), total, {v: catscount, f: catspercentageAnnotation}, {v: dogscount, f: dogsspercentageAnnotation}]);
	  });
  });

  var counter = 0;
  drawChart();

  function drawChart() {
    if(counter < rawData.length){
      chartData.addRow(rawData[counter]);

      // build x-axis ticks to prevent repeated labels
      var dateRange = chartData.getColumnRange(0);
      var ticks = [];
      var dateTick = dateRange.min;
      while (dateTick.getTime() <= dateRange.max.getTime()) {
        ticks.push(dateTick);
        dateTick = new Date(dateTick.getFullYear(), dateTick.getMonth() + 2, 0);
      }
      options.hAxis.ticks = ticks;

      chart.draw(chartData, options);
      counter++;
      window.setTimeout(drawChart, 1000);
    }
  }
}
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js" type="text/javascript" ></script>
   <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
   <div id="chart_div"></div>

      

I've some issues with this chart.

  1. I've data for the months of February and March. But only Feb label is showing up in hAxis label. Expected result is it should show all month labels corresponding to the date in the object.

  2. The haxis month labels are starting from left end and the last month is coming in the very right end. I want to show the label where the data for that month starts in the line chart. ie Suppose I've data upto April, in haxis April label is showing in the right end even if the April data in the line chart begins before the label position.

  3. For the first label in haxis, I want to show the date also. In this case 2020-2-12 is the min data. So in haxis it should show Feb 12 20 and all other labels should be MMM yy only.

Can anyone help me to do the above 3 fixes?

Thanks in advance.


Solution

  • to have the date labels display at the beginning of the month,
    need to use first day of the month...

    dateTick = new Date(dateTick.getFullYear(), dateTick.getMonth() + 1, 1);  // first day
    

    current code uses last day of month (which was based on the data from the other question)

    dateTick = new Date(dateTick.getFullYear(), dateTick.getMonth() + 2, 0);  // last day
    

    next, in order to show the first date in a different format,
    we can use object notation ({}) for the tick,
    where v: is the value of the tick, and f: is the formatted value

    here, we use a date formatter to change the format of the first tick

      // build x-axis ticks to prevent repeated labels
      var dateFormat = new google.visualization.DateFormat({
        pattern: 'yyyy-MM-dd'
      });
      var dateRange = chartData.getColumnRange(0);
      var ticks = [];
      var dateTick = dateRange.min;
      while (dateTick.getTime() <= dateRange.max.getTime()) {
        if (ticks.length === 0) {
          // format first tick
          ticks.push({
            v: dateTick,
            f: dateFormat.formatValue(dateTick)
          });
        } else {
          ticks.push(dateTick);
        }
        dateTick = new Date(dateTick.getFullYear(), dateTick.getMonth() + 1, 1);
      }
    

    see following working snippet...

    google.charts.load('current', {
      packages: ['corechart']
    });
    google.setOnLoadCallback(prepareChartData);
    
    function prepareChartData(){
      var chartData = new google.visualization.DataTable();
      chartData.addColumn('date', 'Date');
      chartData.addColumn('number', 'Total');
      chartData.addColumn('number', 'Dogs');
      chartData.addColumn('number', 'Cats');
      title = 'My Chart';
    
      var options = {
        title: title,
        curveType: 'function',
        legend: {position: 'bottom', alignment: 'start'},
        colors: ['#003f5c', '#ffa600', '#665191', '#f95d6a'],
    
        annotations: {
          alwaysOutside: true,
          textStyle: {
            color: 'black',
            fontSize: 11
          },
        },
        hAxis: {
          format: 'MMM yy',
          viewWindowMode: "explicit",
        },
        vAxis: {
          minValue: 0,
          viewWindowMode: "explicit",
          viewWindow: { min: 0 },
          title: ''
        },
        titleTextStyle: {
          color:'#3a3a3a',
          fontSize:24,
          bold:false
          // fontName: "Segoe UI"
          },
        bar: {groupWidth: '95%'},
        bars: 'horizontal'
      };
    
      var chartDivId = "chart_div";
      var chart = new google.visualization.LineChart(document.getElementById(chartDivId));
      var rawData =[];
    
       var chart_object = { "Feb 20": {monthLabel: "Feb", chartArray:[{'date': "2020-2-12", 'total': "5", 'cats': "10", 'dogs': "10"},{'date': "2020-2-13", 'total': "15", 'cats': "20", 'dogs': "20"}]}, "Mar 20": {monthLabel: "Mar", chartArray:[{'date': "2020-3-10", 'total': "5", 'cats': "10", 'dogs': "10"},{'date': "2020-03-11", 'total': "15", 'cats': "30", 'dogs': "30"}]}};
    
      $.each(chart_object, function(i, chartobject) {
     	$.each(  chartobject.chartArray, function( chartIndex , chartValue ){
    
        date = chartValue['date'];
        total = parseInt(chartValue['total']);
        catscount = parseInt(chartValue['cats']);
        dogscount = parseInt(chartValue['dogs']);
        catspercentage = 0;
        catspercentageAnnotation = catscount+",  percent "+catspercentage+"%";
        dogsspercentage = 0;
        dogsspercentageAnnotation = dogscount+",  percent "+dogsspercentage+"%";
    
        rawData.push([ new Date(date), total, {v: catscount, f: catspercentageAnnotation}, {v: dogscount, f: dogsspercentageAnnotation}]);
    	  });
      });
    
      var counter = 0;
      drawChart();
    
      function drawChart() {
        if(counter < rawData.length){
          chartData.addRow(rawData[counter]);
    
          // build x-axis ticks to prevent repeated labels
          var dateFormat = new google.visualization.DateFormat({
            pattern: 'yyyy-MM-dd'
          });
          var dateRange = chartData.getColumnRange(0);
          var ticks = [];
          var dateTick = dateRange.min;
          while (dateTick.getTime() <= dateRange.max.getTime()) {
            if (ticks.length === 0) {
              // format first tick
              ticks.push({
                v: dateTick,
                f: dateFormat.formatValue(dateTick)
              });
            } else {
              ticks.push(dateTick);
            }
            dateTick = new Date(dateTick.getFullYear(), dateTick.getMonth() + 1, 1);
          }
          options.hAxis.ticks = ticks;
    
          chart.draw(chartData, options);
          counter++;
          window.setTimeout(drawChart, 1000);
        }
      }
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js" type="text/javascript" ></script>
       <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
       <div id="chart_div"></div>