Chart.js中饼图上的单击事件


72

我对Chart.js有疑问。

我使用提供的文档绘制了多个饼图。我想知道是否可以通过单击其中一个图表的某个切片来根据该切片的值进行ajax调用?

例如,如果这是我的 data

var data = [
    {
        value: 300,
        color:"#F7464A",
        highlight: "#FF5A5E",
        label: "Red"
    },
    {
        value: 50,
        color: "#46BFBD",
        highlight: "#5AD3D1",
        label: "Green"
    },
    {
        value: 100,
        color: "#FDB45C",
        highlight: "#FFC870",
        label: "Yellow"
    }
], 

我可以单击Red标记的切片并调用以下格式的网址 example.com?label=red&value=300吗?如果是,我该如何处理?

Answers:


86

更新:作为@Soham Shetty注释,getSegmentsAtEvent(event)仅适用于1.x,并且getElementsAtEvent应使用2.x。

.getElementsAtEvent(e)

在事件点下查找元素,然后在同一数据索引处返回所有元素。内部用于“标签”模式突出显示。

调用getElementsAtEvent(event)Chart实例并传递事件或jQuery事件的参数,将返回该事件在同一位置的点元素。

canvas.onclick = function(evt){
    var activePoints = myLineChart.getElementsAtEvent(evt);
    // => activePoints is an array of points on the canvas that are at the same position as the click event.
};

示例:https//jsfiddle.net/u1szh96g/208/


原始答案(对Chart.js 1.x版本有效):

您可以使用 getSegmentsAtEvent(event)

调用getSegmentsAtEvent(event)Chart实例并传递事件或jQuery事件的参数,将返回该事件在同一位置的segment元素。

来自:原型方法

因此,您可以执行以下操作:

$("#myChart").click( 
    function(evt){
        var activePoints = myNewChart.getSegmentsAtEvent(evt);           
        /* do something */
    }
);  

这是一个完整的工作示例:

<html>
    <head>
        <script type="text/javascript" src="http://code.jquery.com/jquery-2.0.2.js"></script>
        <script type="text/javascript" src="Chart.js"></script>
        <script type="text/javascript">
            var data = [
                {
                    value: 300,
                    color:"#F7464A",
                    highlight: "#FF5A5E",
                    label: "Red"
                },
                {
                    value: 50,
                    color: "#46BFBD",
                    highlight: "#5AD3D1",
                    label: "Green"
                },
                {
                    value: 100,
                    color: "#FDB45C",
                    highlight: "#FFC870",
                    label: "Yellow"
                }
            ];

            $(document).ready( 
                function () {
                    var ctx = document.getElementById("myChart").getContext("2d");
                    var myNewChart = new Chart(ctx).Pie(data);

                    $("#myChart").click( 
                        function(evt){
                            var activePoints = myNewChart.getSegmentsAtEvent(evt);
                            var url = "http://example.com/?label=" + activePoints[0].label + "&value=" + activePoints[0].value;
                            alert(url);
                        }
                    );                  
                }
            );
        </script>
    </head>
    <body>
        <canvas id="myChart" width="400" height="400"></canvas>
    </body>
</html>

6
它适用于1.x版本。对于大于2.x的版本,您需要使用getElementsAtEvent方法。

@SohamShetty,非常感谢您的反馈,我已根据您的评论更新了答案。
托比亚斯

1
谢谢您的回答。我注意到,如果您单击图表(不是细分),则会在控制台中收到错误:未捕获的TypeError:无法读取HTMLCanvasElement.canvas.onclick中未定义的属性“ _chart”
Matt Saunders

@MattSaunders是的,if (activePoints[0])缺少像这样的检查以确保有一些要素。感谢您指出了这一点。我已经更新了示例。
托比亚斯

那个小提琴帮助我解决了我的问题。通过将其置于顶部或其他位置,您可以使其更加明显吗?谢谢
艾米莉

60

使用Chart.JS 2.1.3版,比此版本早的答案不再有效。使用getSegmentsAtEvent(event)方法将在控制台上输出以下消息:

getSegmentsAtEvent不是一个函数

因此,我认为必须将其删除。老实说,我没有阅读任何变更日志。要解决此问题,只需使用Docs中getElementsAtEvent(event)可以找到的方法

在下面可以找到脚本,以获取有效单击的切片标签和值。请注意,检索标签和值也略有不同。

var ctx = document.getElementById("chart-area").getContext("2d");
var chart = new Chart(ctx, config);

document.getElementById("chart-area").onclick = function(evt)
{   
    var activePoints = chart.getElementsAtEvent(evt);

    if(activePoints.length > 0)
    {
      //get the internal index of slice in pie chart
      var clickedElementindex = activePoints[0]["_index"];

      //get specific label by index 
      var label = chart.data.labels[clickedElementindex];

      //get value by index      
      var value = chart.data.datasets[0].data[clickedElementindex];

      /* other stuff that requires slice's label and value */
   }
}

希望能帮助到你。


我创建了一个甜甜圈图,该图在中心孔中显示了一个文本值,是否可以跟踪该文本的点击次数?
techie_28 '16

2
我还应该注意,如果您想获取诸如堆积条形图之类的东西的数据集索引chart.getDatasetAtEvent(evt),则除了chart.getElementsAtEvent(evt)上面的信息之外,还必须使用。
哈特利圣桑

38

Chart.js 2.0使这变得更加容易。

您可以在文档中的常见图表配置下找到它。然后应该在更多的饼图上工作。

options:{
    onClick: graphClickEvent
}

function graphClickEvent(event, array){
    if(array[0]){
        foo.bar; 
    }
}

它在整个图表上触发,但是如果您单击饼图,则该饼图的模型包括可以用来获取值的索引。


4
这是一个方便的答案,因为chart.js的文档中提到了该事件,但目前未提供示例实现:chartjs.org/docs/latest/general/interactions/events.html
汤姆·约翰

22

工作精细图表

ChartJS:饼图-添加选项“ onclick”

              options: {
                    legend: {
                        display: false
                    },
                    'onClick' : function (evt, item) {
                        console.log ('legend onClick', evt);
                        console.log('legd item', item);
                    }
                }

15

从几天开始我一直面临着同样的问题,今天我找到了解决方案。我已经展示了准备执行的完整文件。

<html>
<head><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js">
</script>
</head>
<body>
<canvas id="myChart" width="200" height="200"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        backgroundColor: [
            'rgba(255, 99, 132, 0.2)',
            'rgba(54, 162, 235, 0.2)',
            'rgba(255, 206, 86, 0.2)',
            'rgba(75, 192, 192, 0.2)',
            'rgba(153, 102, 255, 0.2)',
            'rgba(255, 159, 64, 0.2)'
        ],
        borderColor: [
            'rgba(255,99,132,1)',
            'rgba(54, 162, 235, 1)',
            'rgba(255, 206, 86, 1)',
            'rgba(75, 192, 192, 1)',
            'rgba(153, 102, 255, 1)',
            'rgba(255, 159, 64, 1)'
        ],
        borderWidth: 1
    }]
},
options: {
    scales: {
        yAxes: [{
            ticks: {
                beginAtZero:true
            }
        }]
    },
onClick:function(e){
    var activePoints = myChart.getElementsAtEvent(e);
    var selectedIndex = activePoints[0]._index;
    alert(this.data.datasets[0].data[selectedIndex]);


}
}
});
</script>
</body>
</html>

2
谢谢,您的回答有效。简短而精确。应该是公认的答案。
罗恩·道拉古普

5

如果使用的是Donught图表,并且您希望阻止用户在图表圆周围的空白区域内单击时触发事件,则可以使用以下替代方法:

var myDoughnutChart = new Chart(ctx).Doughnut(data);

document.getElementById("myChart").onclick = function(evt){
    var activePoints = myDoughnutChart.getSegmentsAtEvent(evt);

    /* this is where we check if event has keys which means is not empty space */       
    if(Object.keys(activePoints).length > 0)
    {
        var label = activePoints[0]["label"];
        var value = activePoints[0]["value"];
        var url = "http://example.com/?label=" + label + "&value=" + value
        /* process your url ... */
    }
};

4

如果您使用的是TypeScript,则代码会有点时髦,因为没有类型推断,但这可以获取已提供给图表的数据的索引://事件public chartClicked(e:any):void { //console.log(e);

    try {
        console.log('DS ' + e.active['0']._datasetIndex);
        console.log('ID ' +  e.active['0']._index);
        console.log('Label: ' + this.doughnutChartLabels[e.active['0']._index]);
        console.log('Value: ' + this.doughnutChartData[e.active['0']._index]);


    } catch (error) {
        console.log("Error In LoadTopGraph", error);
    }

    try {
        console.log(e[0].active);
    } catch (error) {
        //console.log("Error In LoadTopGraph", error);
    }



}

3

为了成功跟踪点击事件以及用户点击了哪个图形元素,我在.js文件中执行了以下操作,设置了以下变量:

vm.chartOptions = {
    onClick: function(event, array) {
        let element = this.getElementAtEvent(event);
        if (element.length > 0) {
            var series= element[0]._model.datasetLabel;
            var label = element[0]._model.label;
            var value = this.data.datasets[element[0]._datasetIndex].data[element[0]._index];
        }
    }
};
vm.graphSeries = ["Series 1", "Serries 2"];
vm.chartLabels = ["07:00", "08:00", "09:00", "10:00"];
vm.chartData = [ [ 20, 30, 25, 15 ], [ 5, 10, 100, 20 ] ];

然后在我的.html文件中,按如下所示设置图形:

<canvas id="releaseByHourBar" 
    class="chart chart-bar"
    chart-data="vm.graphData"
    chart-labels="vm.graphLabels" 
    chart-series="vm.graphSeries"
    chart-options="vm.chartOptions">
</canvas>

1
  var ctx = document.getElementById('pie-chart').getContext('2d');
 var myPieChart = new Chart(ctx, {
                // The type of chart we want to create
                type: 'pie',

            });

             //define click event
  $("#pie-chart").click(
            function (evt) {
                var activePoints = myPieChart.getElementsAtEvent(evt);
                var labeltag = activePoints[0]._view.label;

                      });

0

您可以在选项部分添加onClick函数,如下所示:

options : {
    cutoutPercentage: 50, //for donuts pie
    onClick: function(event, chartElements){
        if(chartElements){
            console.log(chartElements[0].label);
        }
    },
},

chartElements[0]是图表的点击部分,无需再使用getElementsAtEvent。它适用于Chart v2.9.4


-2

在选项中,放置onclick并以所需的函数作为示例,将所需的ajax调用为例,我将保留该示例,以便每次单击某个点都会告诉您该值,并可以在新函数中使用它。

    options: {
        plugins: {
            // Change options for ALL labels of THIS CHART
            datalabels: {
                color: 'white',
                //backgroundColor:'#ffce00',
                align: 'start'
            }
        },
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true,
                    fontColor: "white"
                },gridLines: {
                        color: 'rgba(255,255,255,0.1)',
                        display: true
                    }
            }],
            xAxes: [{
                ticks: {
                    fontColor: "white"
                },gridLines: {                        
                        display: false
                    }
            }]
        },
        legend: {
        display: false

    },
    //onClick: abre     
        onClick:function(e){ 
    var activePoints = myChart.getElementsAtEvent(e); 
    var selectedIndex = activePoints[0]._index; 
    alert(this.data.datasets[0].data[selectedIndex]); 


} 
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.