簡體   English   中英

Chart.js:條形圖點擊事件

[英]Chart.js: Bar Chart Click Events

我剛剛開始使用 Chart.js,很快就感到非常沮喪。 我的堆積條形圖可以工作,但我無法讓點擊“事件”起作用。

在 GitHub 上找到了nnnick的 nnnick 發表的評論,指出要使用函數getBarsAtEvent ,即使在Chart.js 文檔中根本找不到這個函數(繼續,搜索它)。 該文檔確實提到了chart參考的getElementsAtEvent函數,但這僅適用於折線圖。

我在畫布元素上設置了一個事件偵聽器(以正確的方式):

canv.addEventListener('click', handleClick, false);

...然而在我的handleClick函數中, chart.getBarsAtEvent是未定義的!

現在,在 Chart.js 文檔中,有一條關於為條形圖注冊點擊事件的不同方式的聲明。 這與nnnick 2 年前在 GitHub 上的評論nnnick

全局圖表默認值中,您可以為您的圖表設置一個onClick函數。 我在圖表配置中添加了一個onClick函數,但它什么也沒做...

那么,我到底如何讓點擊回調為我的條形圖工作?!

任何幫助將不勝感激。 謝謝!

PS:我沒有使用 GitHub 的主版本。 我試過了,但它一直在尖叫, require is undefined ,我還沒有准備好包含 CommonJS 以便我可以使用這個圖表庫。 我寧願寫我自己的 dang 圖表。 相反,我下載並使用了直接從文檔頁面頂部的鏈接下載的標准構建版本。

示例:這是我正在使用的配置示例:

var chart_config = {
    type: 'bar',
    data: {
        labels: ['One', 'Two', 'Three'],
        datasets: [
            {
                label: 'Dataset 1',
                backgroundColor: '#848484',
                data: [4, 2, 6]
            },
            {
                label: 'Dataset 2',
                backgroundColor: '#848484',
                data: [1, 6, 3]
            },
            {
                label: 'Dataset 3',
                backgroundColor: '#848484',
                data: [7, 5, 2]
            }
        ]
    },
    options: {
        title: {
            display: false,
            text: 'Stacked Bars'
        },
        tooltips: {
            mode: 'label'
        },
        responsive: true,
        maintainAspectRatio: false,
        scales: {
            xAxes: [
                {
                    stacked: true
                }
            ],
            yAxes: [
                {
                    stacked: true
                }
            ]
        },
        onClick: handleClick
    }
};

我通過查看Chart.js 源代碼設法找到了我的問題的答案。

在 Chart.js, Standard Build 的第 3727 行提供的是.getElementAtEvent方法。 此方法返回我點擊的“圖表元素”。 這里有足夠的數據來確定要在單擊的數據集的鑽取視圖中顯示哪些數據。

chart.getElementAtEvent返回的數組的第一個索引是一個值_datasetIndex 該值顯示被點擊的數據集的索引。

我相信,被點擊的特定欄由值_index 在我的問題中的示例中, _index將指向chart_config.data.labels One

我的handleClick函數現在看起來像這樣:

function handleClick(evt)
{
    var activeElement = chart.getElementAtEvent(evt);

.. where chart是chart.js在做的時候創建的圖表的引用:

chart = new Chart(canv, chart_config);

因此,可以通過單擊選擇的特定數據集如下所示:

chart_config.data.datasets[activeElement[0]._datasetIndex].data[activeElement[0]._index];

你有它。 我現在有一個數據點,我可以從中構建查詢以顯示被點擊的欄的數據。

嗨,這是從 x 和 y 軸獲取值的選項下的點擊事件

onClick: function(c,i) {
    e = i[0];
    console.log(e._index)
    var x_value = this.data.labels[e._index];
    var y_value = this.data.datasets[0].data[e._index];
    console.log(x_value);
    console.log(y_value);
}

我在https://github.com/valor-software/ng2-charts/issues/489找到了這個解決方案

public chartClicked(e: any): void {
  if (e.active.length > 0) {
  const chart = e.active[0]._chart;
  const activePoints = chart.getElementAtEvent(e.event);
  if ( activePoints.length > 0) {
   // get the internal index of slice in pie chart
   const clickedElementIndex = activePoints[0]._index;
   const label = chart.data.labels[clickedElementIndex];
   // get value by index
   const value = chart.data.datasets[0].data[clickedElementIndex];
   console.log(clickedElementIndex, label, value)
  }
 }
}

您可以像這樣使用 onClick。

var worstCells3GBoxChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: lbls,
                    datasets: [{
                        label: 'Worst Cells by 3G',
                        data: datas,
                        backgroundColor: getColorsUptoArray('bg', datas.length),
                        borderColor: getColorsUptoArray('br', datas.length),
                        borderWidth: 1
                    }]
                },
                options: {
                    legend: {
                        display: false
                    },
                    scales: {
                        yAxes: [{
                            ticks: {
                                beginAtZero: true
                            }
                        }]
                    },
                    onClick: function (e) {
                        debugger;
                        var activePointLabel = this.getElementsAtEvent(e)[0]._model.label;
                        alert(activePointLabel);
                    }
                }
            });

做得好! 這似乎返回了繪制的數據值,在許多情況下可能會出現不止一次,因此不清楚點擊了什么。

這將返回被點擊的欄的實際數據標簽。 當深入到一個類別時,我發現這更有用。

chart_config.data.labels[activeElement[0]._index]

我能夠以另一種方式完成這項工作。 可能不受支持,但有時,我發現標簽和值都不足以為我提供填充鑽取所需的信息。

所以我所做的是向數據添加一組自定義屬性:

var ctx = document.getElementById("cnvMyChart").getContext("2d");
if(theChart != null) {theChart.destroy();}
theChart = new Chart(ctx, {
type: typ,
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datakeys: ["thefirstone","thesecondone","thethirdone","thefourthone","thefifthone","thesixthone"],
datasets: [{
    label: '# of Votes',
    data: [12, 19, 3, 5, 2, 3],

...等等

然后,當我需要將鑽取鍵推入另一個 ajax 調用時,我可以通過以下方式獲得它:

var theDrillThroughKey = theChart.config.data.datakeys[activePoints[0]._index];

所以我真的不確定將自定義元素添加到圖表的數據中是否合適,但到目前為止它在 Chrome、IE 和 Firefox 中工作。 我需要能夠在鑽取中放入比我真正想要顯示的更多的信息。

完整示例: https : //wa.rrdsb.com/chartExamples

想法?

我在處理多個數據集時遇到了同樣的問題,並使用了以下解決方法:

var clickOnChart = function(dataIndex){
    ...
}
var lastHoveredIndex = null;
var chart_options = {
    ...
    tooltips: {
        ...
        callbacks: {
            label: function(tooltipItem, chart) {
                var index = tooltipItem.datasetIndex;
                var value  = chart.datasets[index].data[0];
                var label  = chart.datasets[index].label;

                lastHoveredIndex = index;

                return value + "€";
            }
        }
    },
    onClick:function(e, items){
        if ( items.length == 0 ) return; //Clicked outside any bar.

        clickOnChart(lastHoveredIndex);
    }
}

假設您使用如下方法聲明了一個圖表:

  window.myBar = new Chart({chart_name}, {
       type: xxx,
       data: xxx,
       events: ["click"],
       options: {
           ...
       }
  });

聲明 onclick 事件的一個好方法是偵聽畫布點擊,如下所示:

({chart_name}.canvas).onclick = function(evt) {
     var activePoints = myBar.getElementsAtEvent(evt);
     // let's say you wanted to perform different actions based on label selected
     if (activePoints[0]._model.label == "label you are looking for") { ... }
}

Chartjs V3.4.1

在查看了舊版本的解決方案后,這就是 v3 中對我有用的方法:

const onClick = (event, clickedElements) => {
  if (clickedElements.length === 0) return

  const { dataIndex, raw } = clickedElements[0].element.$context
  const barLabel = event.chart.data.labels[dataIndex]
  ...
}
  • raw是點擊欄的值。
  • barLabel是點擊欄的標簽。

您需要將onClick傳遞給條形圖配置:

const barConfig = {
  ...
  options: {
    responsive: true,
    onClick,
    ...
  }
}

在最新的 Chart.js v3.5.1 的圖表選項中

檢查下面的示例代碼

let enterpriseChartOptions = {
    responsive:true,
    maintainAspectRatio: false,
    onClick: (c,i) => {
      console.log('Get the underlying label for click,', c.chart.config._config.data.labels[i[0].index]);
    },
    plugins: { 
      title:{
        text:'Enterprise Dashboard (Health Status of 10 stores) updated every 30 minutes',
        fontSize:20
      },
    },
    scales: {
      x: {
        display: true,
        type: 'category',
        position: 'right',
        ticks: {
          padding: 8,
        },
      },
      y: {
        display: true,
        ticks: {
          callback: function(val, index) {
            // Show the label
            return val < 1 ? "All good" : (val < 2 && val >=1) ? "Warning": val === 2 ? "Critical" : ""; 
          },
          //color: 'red',
          stepSize: 1,
          padding: 8
        }
      }
    },
    layout: {
      padding: {
          left: 20,
          right: 20,
          top: 25,
          bottom: 0
      }
    },

  };

var employeeDetailsCtx = document.getElementById("employee-details").getContext("2d");

                var employee_details_data = {
                    labels: ["Late Present", "On Leave", "Training", "Tour"],
                    datasets: [{
                        label: "Officer",
                        backgroundColor: "#5A8DEE",
                        data: [
                            ...
                        ]
                    }, {
                        label: "Staff",
                        backgroundColor: "#4BC0C0",
                        data: [
                            ...
                        ]
                    }]
                };

                var myoption = {
                    tooltips: {
                        enabled: true
                    },
                    hover: {
                        animationDuration: 1
                    },
                    onClick : function(evt, i) {
                        var activePoint = employeeDetailsBarChart.getElementAtEvent(evt)[0];
                        var data = activePoint._chart.data;
                        var datasetIndex = activePoint._datasetIndex;
                        var label = data.datasets[datasetIndex].label;
                        var value = data.datasets[datasetIndex].data[activePoint._index];
                        e = i[0];
                        var x_value = this.data.labels[e._index];

                        console.log(x_value)
                        console.log(label)
                        console.log(value)
                    },
                    animation: {
                        duration: 1,
                        onComplete: function () {
                            var chartInstance = this.chart,
                                ctx = chartInstance.ctx;
                            ctx.textAlign = 'center';
                            ctx.fillStyle = "rgba(0, 0, 0, 1)";
                            ctx.textBaseline = 'bottom';                              
                            this.data.datasets.forEach(function (dataset, i) {
                                var meta = chartInstance.controller.getDatasetMeta(i);
                                meta.data.forEach(function (bar, index) {
                                    var data = dataset.data[index];
                                    ctx.fillText(data, bar._model.x, bar._model.y - 5);
                                });
                            });
                        }
                    }
                };

                var employeeDetailsBarChart = new Chart(employeeDetailsCtx, {
                    type: 'bar',
                    data: employee_details_data,
                    options: myoption
                });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM