Google Charts: Animation doesn't work for one chart, pointing annotations in the title area

主宰稳场 提交于 2019-12-21 22:45:04

问题


I'm a bit new with google charts, I was playing around to learn it but I got two problems with my chart:

1) I'm not sure why the second chart (red) displays without animation

2) How can I extend the annotation lines with the values to the top of my graph? The best case would be that the values are shown under the chart title

<html>
<head>
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript">
    google.charts.load('current', {
      'packages': ['corechart']
    });
    google.charts.setOnLoadCallback(drawChart);

    function drawChart() {
      var data1 = new google.visualization.DataTable();

      data1.addColumn('number', 'x');
      data1.addColumn('number', 'green');

      data1.addRows([
        [0.005, 3],
        [0.006, 6],
        [0.007, 5],
        [0.008, 8],
        [0.009, 2],
        [0.010, 5],
        [0.011, 5],
        [0.012, 4],
        [0.013, 8]
      ]);

      var data2 = new google.visualization.DataTable();
      data2.addColumn('number', 'x');
      data2.addColumn('number', 'red');

      data2.addRows([
        [0.016, 5],
        [0.017, 1],
        [0.018, 3],
        [0.019, 9],
        [0.020, 4],
        [0.021, 5],
        [0.022, 7],
        [0.023, 7],
        [0.024, 3]
      ]);


      var joinedData = google.visualization.data.join(data1, data2, 'full',
        [[0, 0]], [1], [1]);

      var options = {
        title: 'Playground',
        colors: ['#007F01', '#FE0002'],
        interpolateNulls: true,
        hAxis: {
          title: 'Price',
          titleTextStyle: {
            color: '#333'
          },
          direction: 1,
          format: 'decimal'
        },
        vAxis: {
          direction: 1
        }, 
        orientation: 'horizontal', 

        // customize colum
        series: {
          0: {type: "area"},
          1: {type: "area"},
        },

        // legend: {position : 'left'},
        animation: {
          startup: true,
          duration: 1000,
          easing: 'out',
        }
      };

      var view = new google.visualization.DataView(joinedData);
      view.setColumns([0,
        1,
        {
          calc: "stringify",
          sourceColumn: 1,
          type: "string",
          role: "annotation"
        },
        2,
        {
          calc: "stringify",
          sourceColumn: 2,
          type: "string",
          role: "annotation"
        }
      ]);


      var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
      chart.draw(view, options);

    }
  </script>
</head>

<body>
  <div id="chart_div" style="width: 100%; height: 500px;"></div>

</body>

</html>

Here you can run it: jsfiddle


回答1:


there is bug within google charts when working with data views and animation.
an easy fix is to convert the view back to a data table when drawing the chart...

view.toDataTable()

e.g.

chart.draw(view.toDataTable(), options);

see following working snippet...

google.charts.load('current', {
  packages: ['corechart']
}).then(function () {
  var data1 = new google.visualization.DataTable();

  data1.addColumn('number', 'x');
  data1.addColumn('number', 'green');

  data1.addRows([
    [0.005, 3],
    [0.006, 6],
    [0.007, 5],
    [0.008, 8],
    [0.009, 2],
    [0.010, 5],
    [0.011, 5],
    [0.012, 4],
    [0.013, 8]
  ]);

  var data2 = new google.visualization.DataTable();
  data2.addColumn('number', 'x');
  data2.addColumn('number', 'red');

  data2.addRows([
    [0.016, 5],
    [0.017, 1],
    [0.018, 3],
    [0.019, 9],
    [0.020, 4],
    [0.021, 5],
    [0.022, 7],
    [0.023, 7],
    [0.024, 3]
  ]);


  var joinedData = google.visualization.data.join(data1, data2, 'full',
    [[0, 0]], [1], [1]);

  var options = {
    title: 'Playground',
    colors: ['#007F01', '#FE0002'],
    interpolateNulls: true,
    hAxis: {
      title: 'Price',
      titleTextStyle: {
        color: '#333'
      },
      direction: 1,
      format: 'decimal'
    },
    vAxis: {
      direction: 1
    },
    orientation: 'horizontal',

    // customize colum
    series: {
      0: {type: "area"},
      1: {type: "area"},
    },

    // legend: {position : 'left'},
    animation: {
      startup: true,
      duration: 1000,
      easing: 'out',
    }
  };

  var view = new google.visualization.DataView(joinedData);
  view.setColumns([0,
    1,
    {
      calc: "stringify",
      sourceColumn: 1,
      type: "string",
      role: "annotation"
    },
    2,
    {
      calc: "stringify",
      sourceColumn: 2,
      type: "string",
      role: "annotation"
    }
  ]);

  var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
  chart.draw(view.toDataTable(), options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div" style="width: 100%; height: 500px;"></div>

UPDATE

as for extending the annotation lines,
you can change the length,
but this will just increase the size of each,
and they still will not be aligned at the top

annotations: {
  stem: {
    length: 10
  }
},

the only way would be to modify the chart manually, after it draws
you can move the labels and increase the height of the lines
but this will create two issues

1) the chart will move them back, anytime there is interactivity, such as hovering the labels or data points

to fix, you can use a MutationObserver
this will override the settings, every time the chart tries to move them back

2) if you use chart method getImageURI to get an image of the chart, the changes will not appear

to fix this, use html2canvas to get the image instead of the chart method

see following working snippet...

google.charts.load('current', {
  packages: ['corechart']
}).then(function () {
  var data1 = new google.visualization.DataTable();

  data1.addColumn('number', 'x');
  data1.addColumn('number', 'green');

  data1.addRows([
    [0.005, 3],
    [0.006, 6],
    [0.007, 5],
    [0.008, 8],
    [0.009, 2],
    [0.010, 5],
    [0.011, 5],
    [0.012, 4],
    [0.013, 8]
  ]);

  var data2 = new google.visualization.DataTable();
  data2.addColumn('number', 'x');
  data2.addColumn('number', 'red');

  data2.addRows([
    [0.016, 5],
    [0.017, 1],
    [0.018, 3],
    [0.019, 9],
    [0.020, 4],
    [0.021, 5],
    [0.022, 7],
    [0.023, 7],
    [0.024, 3]
  ]);


  var joinedData = google.visualization.data.join(data1, data2, 'full',
    [[0, 0]], [1], [1]);

  var options = {
    annotations: {
      stem: {
        length: 10
      }
    },
    title: 'Playground',
    colors: ['#007f01', '#fe0002'],
    interpolateNulls: true,
    hAxis: {
      title: 'Price',
      titleTextStyle: {
        color: '#333'
      },
      direction: 1,
      format: 'decimal'
    },
    vAxis: {
      direction: 1
    },
    orientation: 'horizontal',

    // customize colum
    series: {
      0: {type: "area"},
      1: {type: "area"},
    },

    // legend: {position : 'left'},
    animation: {
      startup: true,
      duration: 1000,
      easing: 'out',
    }
  };

  var view = new google.visualization.DataView(joinedData);
  view.setColumns([0,
    1,
    {
      calc: "stringify",
      sourceColumn: 1,
      type: "string",
      role: "annotation"
    },
    2,
    {
      calc: "stringify",
      sourceColumn: 2,
      type: "string",
      role: "annotation"
    }
  ]);

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

  var observer = new MutationObserver(moveAnnotations);
  observer.observe(container, {
    childList: true,
    subtree: true
  });

  function moveAnnotations() {
    var chartLayout = chart.getChartLayoutInterface();
    var chartBounds = chartLayout.getChartAreaBoundingBox();

    var labels = container.getElementsByTagName('text');
    var labelSize = 0;
    Array.prototype.forEach.call(labels, function(label) {
      if (label.getAttribute('text-anchor') === 'middle') {
        if (options.colors.indexOf(label.getAttribute('fill')) > -1) {
          labelSize = (parseFloat(label.getAttribute('font-size')) / 2);
          label.setAttribute('y', chartBounds.top + labelSize);
        }
      }
    });

    var stems = container.getElementsByTagName('rect');
    Array.prototype.forEach.call(stems, function(stem) {
      if ((parseInt(stem.getAttribute('height')) === options.annotations.stem.length) && (stem.getAttribute('fill') === '#999999')) {
        var height = parseFloat(stem.getAttribute('y')) - chartBounds.top;
        stem.setAttribute('height', height);
        stem.setAttribute('y', chartBounds.top + labelSize);
      }
    });
  }

  chart.draw(view.toDataTable(), options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

notes:

1) the move function (moveAnnotations) uses colors from the options in order to identify the annotation labels from the rest of the chart labels
the chart changes all colors to lowercase, so had to change colors in options to lowercase

2) move function also uses option annotations.stem.length to identify the annotation lines



来源:https://stackoverflow.com/questions/50801805/google-charts-animation-doesnt-work-for-one-chart-pointing-annotations-in-the

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