向Google烛台图表添加注释(已发布解决方案触发TypeError)

时间:2017-09-05 23:48:48

标签: javascript charts annotations google-visualization

我正在尝试为Google烛台图表添加一些注释。我注意到有人已经问过同样的问题(Adding annotations to Google Candlestick chart)。用户Aperçu回复了详细解决方案以扩展图表并添加注释,因为图表没有内置任何此类功能。但是,当我尝试此解决方案时,我收到错误“TypeError:document.querySelectorAll( ......)[0]未定义“

这是我的代码:

        chartPoints = [
            ['Budget', 0, 0, 9999, 9999, 'foo1'],
            ['Sales', 0, 0, 123, 123, 'foo2'],
            ['Backlog', 123, 123, 456, 456, 'foo3'],
            ['Hard Forecast', 456, 456, 789, 789, 'foo4'],
            ['Sales to Budget', 789, 789, 1000, 1000, 'foo5']
        ];
        var data = google.visualization.arrayToDataTable(chartPoints, true);
        data.setColumnProperty(5, 'role', 'annotation');
        var options = {
            legend: 'none',
            bar: { groupWidth: '40%', width: '100%' },
            candlestick: {
                fallingColor: { strokeWidth: 0, fill: '#a52714' },
                risingColor: { strokeWidth: 0, fill: '#0f9d58' }
            }
        };    

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

        // attempt to use Aperçu's solution
        const bars = document.querySelectorAll('#chart_div svg > g:nth-child(5) > g')[0].lastChild.children // this triggers a TypeError
        for (var i = 0 ; i < bars.length ; i++) {
          const bar = bars[i]
          const { top, left, width } = bar.getBoundingClientRect()
          const hint = document.createElement('div')
          hint.style.top = top + 'px'
          hint.style.left = left + width + 5 + 'px'
          hint.classList.add('hint')
          hint.innerText = rawData.filter(t => t[1])[i][0]
          document.getElementById('chart_div').append(hint)
        }

我希望图表显示栏旁边的最后一段数据(即“foo1”,“foo2”等)

1 个答案:

答案 0 :(得分:3)

每个蜡烛或酒吧将由<rect>元素

表示

我们可以使用上升和下降颜色将条形与图表中的其他<rect>元素分开

数据表中的行数与条数相同

一旦找到第一个条形码,我们可以使用零rowIndex来从数据中提取值

我们需要找到上升/下降的值,以了解放置注释的位置

然后使用图表方法查找注释的位置

  

getChartLayoutInterface() - 返回一个对象,其中包含有关图表及其元素的屏幕位置信息。

     

getYLocation(position, optional_axis_index) - 返回相对于图表容器的位置的屏幕y坐标。

请参阅以下工作代码组 添加了两个注释 一个是因为上升和下降之间的差异 另一个是具有注释角色的列中的值

&#13;
&#13;
google.charts.load('current', {
  callback: drawChart,
  packages: ['corechart']
});

function drawChart() {
  var chartPoints = [
    ['Budget', 0, 0, 9999, 9999, 'foo1'],
    ['Sales', 0, 0, 123, 123, 'foo2'],
    ['Backlog', 123, 123, 456, 456, 'foo3'],
    ['Hard Forecast', 456, 456, 789, 789, 'foo4'],
    ['Sales to Budget', 789, 789, 1000, 1000, 'foo5']
  ];
  var data = google.visualization.arrayToDataTable(chartPoints, true);
  data.setColumnProperty(5, 'role', 'annotation');
  var options = {
    legend: 'none',
    bar: { groupWidth: '40%', width: '100%' },
    candlestick: {
      fallingColor: { strokeWidth: 0, fill: '#a52714' },
      risingColor: { strokeWidth: 0, fill: '#0f9d58' }
    }
  };

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

  google.visualization.events.addListener(chart, 'ready', function () {
    var annotation;
    var bars;
    var chartLayout;
    var formatNumber;
    var positionY;
    var positionX;
    var rowBalance;
    var rowBottom;
    var rowIndex;
    var rowTop;
    var rowValue;
    var rowWidth;

    chartLayout = chart.getChartLayoutInterface();
    rowIndex = 0;
    formatNumber = new google.visualization.NumberFormat({
      pattern: '#,##0'
    });

    bars = container.getElementsByTagName('rect');
    for (var i = 0; i < bars.length; i++) {
      switch (bars[i].getAttribute('fill')) {
        case '#a52714':
        case '#0f9d58':
          rowWidth = parseFloat(bars[i].getAttribute('width'));
          if (rowWidth > 2) {
            rowBottom = data.getValue(rowIndex, 1);
            rowTop = data.getValue(rowIndex, 3);
            rowValue = rowTop - rowBottom;
            rowBalance = Math.max(rowBottom, rowTop);
            positionY = chartLayout.getYLocation(rowBalance) - 6;
            positionX = parseFloat(bars[i].getAttribute('x'));

            // row value
            annotation = container.getElementsByTagName('svg')[0].appendChild(container.getElementsByTagName('text')[0].cloneNode(true));
            annotation.textContent = formatNumber.formatValue(rowValue);
            annotation.setAttribute('x', (positionX + (rowWidth / 2)));
            annotation.setAttribute('y', positionY);
            annotation.setAttribute('font-weight', 'bold');

            // annotation column
            annotation = container.getElementsByTagName('svg')[0].appendChild(container.getElementsByTagName('text')[0].cloneNode(true));
            annotation.textContent = data.getValue(rowIndex, 5);
            annotation.setAttribute('x', (positionX + (rowWidth / 2)));
            annotation.setAttribute('y', positionY - 18);
            annotation.setAttribute('font-weight', 'bold');

            rowIndex++;
          }
          break;
      }
    }
  });

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