Search code examples
javascriptchartsgoogle-visualizationtimeline.js

google chart timeline with different moments in row


I have a google chart timeline with a list of different contracts in each row. Having the start and end date is easy, but i also want do show specific moments in each row (let's say tenant contract deadline, and other important moments) - it could be something like a dot in the date of that moment.

I have already search a lot but can't find a example

this is what i have: sample code and here is my code:

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

    function drawChart() {
      var data = new google.visualization.DataTable();
      data.addColumn('string', 'Team');
      data.addColumn('date', 'Season Start Date');
      data.addColumn('date', 'Season End Date');

      data.addRows([
['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],
['drwerwer', new Date(2018, 9, 25), new Date(2019, 11, 31)],
['WBOX LDA', new Date(2019, 0, 01), new Date(2025, 0, 01)]]);

var options = {
  height: 450,
  timeline: {
    groupByRowLabel: false
  }
};

var chart = new google.visualization.Timeline(document.getElementById('chart_div'));

chart.draw(data, options);
}

Solution

  • see addMarker in the following working snippet.
    which has been modified from the answer found here.
    vertical reference line in google timeline visualization

    usage, provide date of event, the data table row on which it should appear, and the text to dispaly...

    addMarker(new Date(), 3, 'Test Event');
    

    google.charts.load('current', {
      packages:['timeline']
    }).then(function () {
      var container = document.getElementById('chart_div');
      var chart = new google.visualization.Timeline(container);
      var dataTable = new google.visualization.DataTable();
      dataTable.addColumn({type: 'string', id: 'Row'});
      dataTable.addColumn({type: 'string', id: 'Bar'});
      dataTable.addColumn({type: 'date', id: 'Start'});
      dataTable.addColumn({type: 'date', id: 'End'});
      var currentYear = (new Date()).getFullYear();
      dataTable.addRows([
        ['Row 1', 'A-1', new Date(currentYear, 0, 1), new Date(currentYear, 2, 31)],
        ['Row 1', 'A-2', new Date(currentYear, 3, 1), new Date(currentYear, 5, 30)],
        ['Row 2', 'B-1', new Date(currentYear, 6, 1), new Date(currentYear, 8, 31)],
        ['Row 2', 'B-2', new Date(currentYear, 9, 1), new Date(currentYear, 11, 31)]
      ]);
      var dataTableGroup = google.visualization.data.group(dataTable, [0]);
      var dateRangeStart = dataTable.getColumnRange(2);
      var dateRangeEnd = dataTable.getColumnRange(3);
      var formatDate = new google.visualization.DateFormat({
        pattern: 'MM/dd/yyyy'
      });
      var rowHeight = 44;
      var options = {
        height: (dataTableGroup.getNumberOfRows() * rowHeight) + rowHeight
      };
      
      function drawChart() {
        chart.draw(dataTable, options);
      }
    
      function addMarker(markerDate, row, label) {
        var baseline;
        var baselineBounds;
        var chartElements;
        var markerLabel;
        var markerLine;
        var markerSpan;
        var svg;
        var timeline;
        var timelineRect;
        var timelineUnit;
        var timelineWidth;
        var timespan;
    
        baseline = null;
        timeline = null;
        svg = null;
        markerLabel = null;
        chartElements = container.getElementsByTagName('svg');
        if (chartElements.length > 0) {
          svg = chartElements[0];
        }
        chartElements = container.getElementsByTagName('rect');
        if (chartElements.length > 0) {
          var rowIndex = 0;
          Array.prototype.forEach.call(chartElements, function(rect) {
            switch (rect.getAttribute('fill')) {
              case 'none':
              case '#ffffff':
              case '#e6e6e6':
                // ignore
                break;
    
              default:
                console.log(rowIndex, row, (rowIndex === row));
                if (rowIndex === row) {
                  timelineRect = rect;
                  console.log(timelineRect);
                }
                rowIndex++;
            }
          });
          timeline = chartElements[0];
        }
        chartElements = container.getElementsByTagName('path');
        if (chartElements.length > 0) {
          baseline = chartElements[0];
        }
        chartElements = container.getElementsByTagName('text');
        if (chartElements.length > 0) {
          markerLabel = chartElements[0].cloneNode(true);
        }
        if ((svg === null) || (timeline === null) || (timelineRect === null) || (baseline === null) || (markerLabel === null) ||
            (markerDate.getTime() < dateRangeStart.min.getTime()) ||
            (markerDate.getTime() > dateRangeEnd.max.getTime())) {
          return;
        }
    
        // calculate placement
        timelineWidth = parseFloat(timeline.getAttribute('width'));
        baselineBounds = baseline.getBBox();
        timespan = dateRangeEnd.max.getTime() - dateRangeStart.min.getTime();
        timelineUnit = (timelineWidth - baselineBounds.x) / timespan;
        markerSpan = markerDate.getTime() - dateRangeStart.min.getTime();
    
        // add label
        svg.appendChild(markerLabel);
        markerLabel.setAttribute('text-anchor', 'start');
        markerLabel.setAttribute('fill', '#000000');
        markerLabel.setAttribute('y', parseFloat(timelineRect.getAttribute('y')) + parseFloat(markerLabel.getAttribute('font-size')));
        markerLabel.setAttribute('x', (baselineBounds.x + (timelineUnit * markerSpan) + 4));
        markerLabel.textContent = label;
    
        // add line
        markerLine = timeline.cloneNode(true);
        markerLine.setAttribute('y', timelineRect.getAttribute('y'));
        markerLine.setAttribute('x', (baselineBounds.x + (timelineUnit * markerSpan)));
        markerLine.setAttribute('height', timelineRect.getAttribute('height'));
        markerLine.setAttribute('width', 1);
        markerLine.setAttribute('stroke', 'none');
        markerLine.setAttribute('stroke-width', '0');
        markerLine.setAttribute('fill', '#000000');
        svg.appendChild(markerLine);
      }
    
      google.visualization.events.addListener(chart, 'ready', function () {
        // add marker for current date
        addMarker(new Date(), 3, 'Test Event');
      });
    
      window.addEventListener('resize', drawChart, false);
      drawChart();
    });
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="chart_div"></div>