Acabo de comenzar a trabajar con Chart.js, y me estoy frustrando muy rápidamente. Tengo mi gráfico de barras apiladas funcionando, pero no puedo hacer que funcionen los "eventos" de clic.

He encontrado un comentario sobre GitHub al nnnick de Chart.js indicando para usar la función getBarsAtEvent, aunque esta función no se puede encontrar en la documentación de Chart.js en absoluto (adelante, búscalo). La documentación menciona la función getElementsAtEvent de la referencia chart, pero eso es solo para gráficos de líneas.

Configuré un detector de eventos (de la manera correcta) en mi elemento de lienzo:

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

... sin embargo, en mi función handleClick, chart.getBarsAtEvent no está definida!

Ahora, en el documento Chart.js, hay una declaración sobre una forma diferente de registrar el evento de clic para el gráfico de barras. Es muy diferente al comentario de nnnick sobre GitHub de hace 2 años.

En el Valores predeterminados del gráfico global puede establecer una función onClick para su gráfico. Agregué una función onClick a mi configuración de gráfico, y no hizo nada ...

Entonces, ¿cómo diablos hago que la devolución de llamada al hacer clic funcione para mi gráfico de barras?

Cualquier ayuda sería muy apreciada. ¡Gracias!

P.S .: no estoy usando la compilación maestra de GitHub. Lo intenté, pero seguía gritando que require is undefined y no estaba listo para incluir CommonJS solo para poder usar esta biblioteca de gráficos. Prefiero escribir mis propios gráficos. En cambio, descargué y estoy usando la Standard Build versión que descargué directamente desde el enlace en la parte superior de la página de documentación.

EJEMPLO: Aquí hay un ejemplo de la configuración que estoy usando:

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
    }
};
30
WebWanderer 9 may. 2016 a las 21:03

8 respuestas

La mejor respuesta

Logré encontrar la respuesta a mi pregunta mirando a través de Código fuente de Chart.js.

En la línea 3727 de Chart.js, Standard Build, se encuentra el método .getElementAtEvent. Este método me devuelve el "elemento gráfico" en el que se hizo clic. Aquí hay suficientes datos para determinar qué datos mostrar en una vista detallada del conjunto de datos en el que se hizo clic.

En el primer índice de la matriz devuelto por chart.getElementAtEvent hay un valor _datasetIndex. Este valor muestra el índice del conjunto de datos en el que se hizo clic.

La barra específica en la que se hizo clic, creo, se observa con el valor _index. En mi ejemplo en mi pregunta, _index apuntaría a One en chart_config.data.labels.

Mi función handleClick ahora se ve así:

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

..where chart es la referencia del gráfico creado por chart.js al hacer:

chart = new Chart(canv, chart_config);

Por lo tanto, el conjunto específico de datos que seleccionó el clic se puede encontrar como:

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

Y ahí lo tienes. Ahora tengo un punto de datos desde el que puedo construir una consulta para mostrar los datos de la barra en la que se hizo clic.

45
ArtemStorozhuk 9 jun. 2016 a las 10:38

Encontré esta solución en https://github.com/valor-software/ng2- cuadros / números / 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)
  }
 }
}
8
Asif Karim Bherani 5 mar. 2018 a las 19:55

Digamos que declaró un gráfico utilizando un método como este:

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

Una buena manera de declarar los eventos onclick implicaría escuchar el clic del lienzo, así:

({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") { ... }
}
0
Marquistador 11 mar. 2017 a las 16:27

¡Bien hecho! Sin embargo, esto parece devolver el valor de los datos que se grafican, que en muchos casos podrían aparecer más de una vez, por lo que no está claro en qué se hizo clic.

Esto devolverá la etiqueta de datos real de la barra en la que se hace clic. Encontré esto más útil al profundizar en una categoría.

chart_config.data.labels[activeElement[0]._index]
3
Matt R O'Connor 29 jun. 2016 a las 08:02

Hola, este es el evento de clic en las opciones que está obteniendo valores de los ejes x e 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);
}
37
Max 14 feb. 2018 a las 14:54

Puedes usar onClick así.

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);
                    }
                }
            });
1
Abdullah Shahid 12 feb. 2020 a las 19:22

Tuve el mismo problema con múltiples conjuntos de datos y usé esta solución:

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);
    }
}
1
sergio0983 27 ago. 2019 a las 11:03

Pude hacer que esto funcionara de otra manera. Es posible que no sea compatible, pero a veces, encuentro que ni la etiqueta ni el valor son adecuados para obtener la información necesaria para completar un desglose.

Entonces, lo que hice fue agregar un conjunto personalizado de atributos a los datos:

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],

... etc.

Luego, cuando necesito presionar la tecla de obtención de detalles en otra llamada ajax, pude obtenerlo con esto:

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

Por lo tanto, no estoy seguro de que sea apropiado agregar elementos personalizados a los datos del Gráfico, pero hasta ahora funciona en Chrome, IE y Firefox. Necesitaba poder poner más información en la obtención de detalles de la que realmente quería mostrar.

Ejemplo de lo completo: https://wa.rrdsb.com/chartExamples

¿Pensamientos?

1
Chris Denby 6 mar. 2017 a las 20:59