Search code examples
javascriptchartsgoogle-visualization

Google chart, I want to write some text at the right of each point in graph


Google chart, I want to write some text at the right side of some points in the graph. How can I do that?

The chart has three different series Low, High, Multiple, A dashed line should be there which starts from "Low" value to "Multiple" value. X axis should have Ticks like PC#1, PC#2, PC#3 etc. Also each point should have its value at the right of it within the graph not as tool-tip. The graph should have three legends as we have three series "Low", "High", "Multiple".

Please click on this image link to understand my requirement


Solution

  • you can place text next to a point on a chart using annotations

    annotations are added using a data column, directly following the series column it should represent

    see following working snippet...

    google.charts.load('current', {
      callback: function () {
        drawVisualization();
        window.addEventListener('resize', drawVisualization, false);
      },
      packages:['corechart']
    });
    function drawVisualization() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'x');
      data.addColumn('number', 'y');
      data.addColumn({type: 'string', role: 'annotation'});
      data.addRow([{v: 2, f: ''}, 0.8, '0.8x']);
      data.addRow([{v: 2, f: ''}, 7.4, '7.4x']);
      data.addRow([{v: 2, f: ''}, 12.2, '12.2x']);
    
      var container = document.getElementById('visualization');
      var chart = new google.visualization.ScatterChart(container);
    
      chart.draw(data, {
        hAxis: {
          ticks: [
            {v: 0, f: ''},
            {v: 1, f: ''},
            {v: 2, f: ''},
            {v: 3, f: ''},
            {v: 4, f: ''}
          ]
        }
      });
    }
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="visualization"></div>


    by default, annotations are placed above the point, as seen in the above snippet

    and there are no standard options available to move the annotation left or right

    only up or down using --> annotations.stem.length

    in order to set the text to the right of the point,
    the text needs to be moved manually,
    when the 'ready' event fires on the chart

    see following working snippet...

    the annotations will be added as text elements to the svg

    when the ready event fires, the annotation text elements are found,
    and the 'x' attribute is changed, to move the text to the right

    annotations.stem.length is used to bring the text down to the same height as the point

    google.charts.load('current', {
      callback: function () {
        drawVisualization();
        window.addEventListener('resize', drawVisualization, false);
      },
      packages:['corechart']
    });
    function drawVisualization() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'x');
      data.addColumn('number', 'y');
      data.addColumn({type: 'string', role: 'annotation'});
      data.addRow([{v: 2, f: ''}, 0.8, '0.8x']);
      data.addRow([{v: 2, f: ''}, 7.4, '7.4x']);
      data.addRow([{v: 2, f: ''}, 12.2, '12.2x']);
    
      var container = document.getElementById('visualization');
      var chart = new google.visualization.ScatterChart(container);
    
      google.visualization.events.addOneTimeListener(chart, 'ready', function () {
        Array.prototype.forEach.call(container.getElementsByTagName('text'), function (text, index) {
          if (text.getAttribute('text-anchor') === 'middle') {
            text.setAttribute('x', parseFloat(text.getAttribute('x')) + 20);
          }
        });
      });
    
      chart.draw(data, {
        annotations: {
          stem: {
            length: -5
          }
        },
        hAxis: {
          ticks: [
            {v: 0, f: ''},
            {v: 1, f: ''},
            {v: 2, f: ''},
            {v: 3, f: ''},
            {v: 4, f: ''}
          ]
        }
      });
    }
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="visualization"></div>


    however, you will notice in the above snippet,
    when you hover over one of the points,
    the chart will set the text back to the original 'x' position

    this can be prevented by turning off interactivity using the following option...
    enableInteractivity: false

    but if you would like to keep interactivity,
    you'll need to reset the 'x' position anytime an event occurs

    this can be accomplished by using a MutationObserver

    see following working snippet...

    when the 'ready' event fires, the new 'x' position is calculated for each text element

    then the MutationObserver is used to reset the position,
    anytime interactivity occurs...

    google.charts.load('current', {
      callback: function () {
        drawVisualization();
        window.addEventListener('resize', drawVisualization, false);
      },
      packages:['corechart']
    });
    function drawVisualization() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'x');
      data.addColumn('number', 'y');
      data.addColumn({type: 'string', role: 'annotation'});
      data.addRow([{v: 2, f: ''}, 0.8, '0.8x']);
      data.addRow([{v: 2, f: ''}, 7.4, '7.4x']);
      data.addRow([{v: 2, f: ''}, 12.2, '12.2x']);
    
      var container = document.getElementById('visualization');
      var chart = new google.visualization.ScatterChart(container);
    
      var annotations = {};
      google.visualization.events.addOneTimeListener(chart, 'ready', function () {
        Array.prototype.forEach.call(container.getElementsByTagName('text'), function (text, index) {
          if (text.getAttribute('text-anchor') === 'middle') {
            annotations[index] = parseFloat(text.getAttribute('x')) + 20;
          }
        });
    
        var observer = new MutationObserver(function () {
          Array.prototype.forEach.call(container.getElementsByTagName('text'), function (text, index) {
            if (text.getAttribute('text-anchor') === 'middle') {
              text.setAttribute('x', annotations[index]);
            }
          });
        });
        observer.observe(container, {
          childList: true,
          subtree: true
        });
      });
    
      chart.draw(data, {
        annotations: {
          stem: {
            length: -5
          }
        },
        hAxis: {
          ticks: [
            {v: 0, f: ''},
            {v: 1, f: ''},
            {v: 2, f: ''},
            {v: 3, f: ''},
            {v: 4, f: ''}
          ]
        }
      });
    }
    <script src="https://www.gstatic.com/charts/loader.js"></script>
    <div id="visualization"></div>