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

标签 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”等)

最佳答案

每个蜡烛图或柱形图都由一个 <rect> 元素表示

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

将有与数据表中的行数相同的条形

一旦找到第一个柱,我们就可以使用零的 rowIndex 从数据中提取值

我们需要找到上升/下降的值,才能知道在哪里放置注释

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

getChartLayoutInterface() - Returns an object containing information about the onscreen placement of the chart and its elements.

getYLocation(position, optional_axis_index) - Returns the screen y-coordinate of position relative to the chart's container.

请参阅以下工作片段
添加了两个注解
一为涨跌之别
另一个为具有注释作用的列中的值

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);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

关于javascript - 向 Google 烛台图表添加注释(发布的解决方案触发 TypeError),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46064803/

相关文章:

python - 有没有办法在 XlsxWriter 中创建图表而不将数据写入工作表中的单元格? IE。来自 python 脚本中的数组?

java - 如何创建作为一组 jackson 注释的注释?

javascript - 停止和启动页面溢出/单击时滚动的能力

javascript - 多个表单 onclick 事件仅适用于第一个表单

python - 如何在 xlsxwriter add_series() 中从行列表示法转换为 A1 表示法

spring - JAX-WS 的注释端点位置

java - Spring MVC 如何转换 @RequestParam 值?

javascript - Google Analytics onClick 发送事件

javascript - webpack - 找不到 manifest.json

charts - 如何使用 lavacharts 和 laravel 创建动态图表?