首页 > 解决方案 > 向折线图添加区域

问题描述

我正在尝试绘制一个折线图,其中 X 轴是日期(请参阅此链接)。

var totalChartOptions = {
    chart : {title : 'Total cases'},
    curveType : 'function',
    legend : {position : 'none'},
    axes : {x : {0 : {side : 'top'}}},
    hAxis : {title : '', format : "dd/MM"},
    colors : [ 'orange', 'green', 'red' ],
    pointSize : 20,
    pointShape : 'diamond',
}

totalData.addColumn("date", "Date");
totalData.addColumn("number", "Confirmed");
totalData.addColumn("number", "Recovered");
totalData.addColumn("number", "Deaths");
... foreach (...)
        totalData.addRow([ date, confirmed, recovered, deaths, null ]);
... var chart = new google.charts.Line(totalElement);
chart.draw(totalData, google.charts.Line.convertOptions(vm.totalChartOptions));

对于“今天”,我想添加一个彩色区域以显示数据尚未最终确定。

在此处输入图像描述.

但是,我不希望该区域是用户交互的(添加另一个图表),只是现有区域的特定背景。我怎么做?

标签: chartsgoogle-visualization

解决方案


材料图表不支持组合图表,
因此无法混合使用线和区域系列'

还有几个不支持的配置选项,
请参阅材料图表特征奇偶校验的跟踪问题...

经典图表没有在顶部显示 x 轴的选项。但是,我们可以手动修改事件
图表。 为了解决这个问题,我们使用经典图表,并手动将 x 轴标签移动到顶部。 'ready'

使用ComboChart,我们可以将第四个系列添加为一个区域。

totalData.addColumn('date', 'Date');
totalData.addColumn('number', 'Confirmed');
totalData.addColumn('number', 'Recovered');
totalData.addColumn('number', 'Deaths');
totalData.addColumn('number', 'Today');  // <-- area series

并添加以下选项,将主要系列类型设置为线,
并将第四系列更改为区域。

seriesType: 'line',
series: {
  3: {
    type: 'area',
    color: 'yellow',
    pointSize: 0
  }
}

为了将该区域显示为图表区域的整个高度,
我们需要找到图表上显示的最大值(或对其进行硬编码)。

// calculate y-axis range
var range = {
  min: null,
  max: null
};
for (var i = 1; i < totalData.getNumberOfColumns(); i++) {
  var colRange = totalData.getColumnRange(i);
  range.min = Math.min(range.min, colRange.min);
  range.max = Math.max(range.max, colRange.max);
}

并且该区域至少需要两个行值,
在以下代码段中,我们使用带有今天日期的行,
并添加一个额外的日期,否则为空白值。

// add area series data
var colIndex = totalData.getNumberOfColumns() - 1;
totalData.setValue(totalData.getNumberOfRows() - 2, colIndex, range.max);
totalData.setValue(totalData.getNumberOfRows() - 1, colIndex, range.max);

请参阅以下工作片段...

google.charts.load('current', {
  packages: ['corechart']
}).then(function () {
  var totalData = new google.visualization.DataTable();
  totalData.addColumn('date', 'Date');
  totalData.addColumn('number', 'Confirmed');
  totalData.addColumn('number', 'Recovered');
  totalData.addColumn('number', 'Deaths');
  totalData.addColumn('number', 'Today');

  // simulate data
  totalData.addRow([new Date(2020, 2, 18), 1900, 0, 1, null]);
  totalData.addRow([new Date(2020, 2, 20), 1900, 0, 10, null]);
  totalData.addRow([new Date(2020, 2, 22), 4000, 2000, 100, null]);
  totalData.addRow([new Date(2020, 2, 24), 4000, 2000, 100, null]);
  totalData.addRow([new Date(2020, 2, 26), 2400, 0, 100, null]);
  totalData.addRow([new Date(2020, 2, 28), 3000, 1000, 110, null]);
  totalData.addRow([new Date(2020, 2, 30), 4000, 1000, 90, null]);
  totalData.addRow([new Date(2020, 3, 1), 4300, 5000, 20, null]);
  totalData.addRow([new Date(2020, 3, 3), 0, 0, 0, null]);
  totalData.addRow([new Date(2020, 3, 4), null, null, null, null]);

  // calculate y-axis range
  var range = {
    min: null,
    max: null
  };
  for (var i = 1; i < totalData.getNumberOfColumns(); i++) {
    var colRange = totalData.getColumnRange(i);
    range.min = Math.min(range.min, colRange.min);
    range.max = Math.max(range.max, colRange.max);
  }

  // add area series data
  var colIndex = totalData.getNumberOfColumns() - 1;
  totalData.setValue(totalData.getNumberOfRows() - 2, colIndex, range.max);
  totalData.setValue(totalData.getNumberOfRows() - 1, colIndex, range.max);

  var totalChartOptions = {
    chartArea: {
      top: 60
    },
    title : 'Total cases',
    curveType: 'function',
    legend: {position : 'none'},
    hAxis: {title : '', format : 'dd/MM'},
    colors: ['orange', 'green', 'red', 'yellow'],
    pointSize: 20,
    pointShape: 'diamond',
    vAxis: {
      viewWindow: range
    },
    seriesType: 'line',
    series: {
      3: {
        type: 'area',
        color: 'yellow',
        pointSize: 0
      }
    },
    theme: 'material'
  }

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

  // move x-axis to top
  google.visualization.events.addListener(chart, 'ready', function () {
    var chartLayout = chart.getChartLayoutInterface();
    var chartBounds = chartLayout.getChartAreaBoundingBox();
    var labels = chart.getContainer().getElementsByTagName('text');
    var fontSize;
    var yCoord;
    Array.prototype.forEach.call(labels, function(label) {
      fontSize = parseFloat(label.getAttribute('font-size'));
      switch (label.getAttribute('text-anchor')) {
        // chart title
        case 'start':
          yCoord = parseFloat(label.getAttribute('y'));
          label.setAttribute('y', yCoord - fontSize);
          break;

        // x-axis labels
        case 'middle':
          label.setAttribute('y', chartBounds.top - (fontSize / 2));
          break;

        // y-axis labels
        default:
          // ignore
      }
    });
  });

  chart.draw(totalData, totalChartOptions);
});
#chart_div {
  height: 400px;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>


推荐阅读