2017-09-05 60 views
2

我正在嘗試向Google燭臺圖表添加一些註釋。我注意到有人已經問過同樣的問題(Adding annotations to Google Candlestick chart)。用戶Aperçu回答了一個詳細的解決方案,以擴展圖表並添加註釋,因爲圖表沒有內置任何此類功能。但是,當我嘗試此解決方案時,出現「TypeError:document.querySelectorAll(...) [0]是未定義」向Google燭臺圖表添加註釋(發佈解決方案觸發器TypeError)

這是我的代碼:

 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

檢查[這個答案](https://stackoverflow.com/a/41857399/5090771)... – WhiteHat

+0

嗨,這是一個非常長的答案,我不確定我需要改變它以使其與我的代碼一起工作。我嘗試在底部粘貼(從var waterFallChart = new google.visualization.ChartWrapper({到最後減去jquery的東西),但是我得到錯誤ReferenceError:dataChart沒有被定義,只是需要很多東西你可以向我解釋一下,我可以重構這個,使它與上面的代碼一起工作嗎? – ag415

+0

我試圖將dataChart更改爲chartPoints,但現在我得到錯誤:未知的頭文件類型:0 – ag415

回答

2

每個蠟燭或酒吧將代表一個<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>

+0

嗨Whitehat,謝謝你的詳細解釋和代碼示例。我試圖修改這個沒有jQuery的工作,但我有一個小問題我改變了開始的路線用「$(annotation)」爲for循環(var i = 0;我 ag415

+0

啊我的錯誤,忘記了innerHTML是一種屬性而不是一種方法!我沒有jQuery的工作,for循環也沒有必要。只需要更改$(annotation).text(value)的每個實例;與註釋。innerHTML = value;感謝您的幫助WhiteHat! – ag415

+1

歡呼!很高興幫助,我刪除了jquery ... – WhiteHat