8

I want to make my pie-chart interactive by allowing the user to double-click on a slice to drill down. I believe that the way to do this is to create an onclick handler on the canvas, and use getSegmentsAtEvent() to determine which slice was clicked.

The segment data returned by the call to getSegmentsAtEvent() is possibly ambiguous though. Here is a sample of the returned data:

[{ "circumference": 4.1887902047863905, "endAngle": 8.901179185171081, "fillColor": "#FF5A5E", "highlightColor": "#FF5A5E", "innerRadius": 0, "label": "Red", "outerRadius": 99.5, "showStroke": true, "startAngle": 4.71238898038469, "strokeColor": "#fff", "strokeWidth": 2, "value": 300 }] 

Of those fields, only value, fillColor, highlightColor, and label are supplied by me, and none of them are necessarily unique. I could ensure that label is unique, but that might make it less readable for humans.

I have tried adding an additional property (e.g. "id") into the data I pass into Pie(), but it is stripped out when I get the segment data back from this call. Is there a way to add a property to each segment which I can use to positively identify them, without overloading the label field?

1
  • hi was the below answer what you were looking for? Commented Apr 9, 2015 at 8:20

2 Answers 2

7

You would need to either override the pie chart or create a new chart type that inherits from pie.

Here is an example of a new chart type, i have passed a new attribute called id and then the only thing that needs to be different in this chart is that when the data is being added this id needs to passed to the chart

Chart.types.Pie.extend({ name: "PieUnique", addData: function (segment, atIndex, silent) { var index = atIndex || this.segments.length; this.segments.splice(index, 0, new this.SegmentArc({ value: segment.value, outerRadius: (this.options.animateScale) ? 0 : this.outerRadius, innerRadius: (this.options.animateScale) ? 0 : (this.outerRadius / 100) * this.options.percentageInnerCutout, fillColor: segment.color, highlightColor: segment.highlight || segment.color, showStroke: this.options.segmentShowStroke, strokeWidth: this.options.segmentStrokeWidth, strokeColor: this.options.segmentStrokeColor, startAngle: Math.PI * this.options.startAngle, circumference: (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value), label: segment.label, //add option passed id: segment.id })); if (!silent) { this.reflow(); this.update(); } }, }); var pieData = [{ value: 300, color: "#F7464A", highlight: "#FF5A5E", label: "Red", id: "1-upi" }, { value: 50, color: "#46BFBD", highlight: "#5AD3D1", label: "Green", id: "2-upi" }, { value: 100, color: "#FDB45C", highlight: "#FFC870", label: "Yellow", id: "3-upi" }, { value: 40, color: "#949FB1", highlight: "#A8B3C5", label: "Grey", id: "4-upi" }, { value: 120, color: "#4D5360", highlight: "#616774", label: "Dark Grey", id: "5-upi" } ]; var ctx = document.getElementById("chart-area").getContext("2d"); window.myPie = new Chart(ctx).PieUnique(pieData); document.getElementById("chart-area").onclick = function (evt) { var activePoints = window.myPie.getSegmentsAtEvent(evt); //you can now access the id at activePoints[0].id console.log(activePoints); };
<script src="https://raw.githack.com/leighquince/Chart.js/master/Chart.js"></script> <canvas id="chart-area" width="400"></canvas>

Sign up to request clarification or add additional context in comments.

2 Comments

Big thanks! Works great with Doughnut charts. addData() Method taken from Chart.js source.
note that if you don't have the options.startAngle set, the chart won't show up. the default value (from the source code) is Math.PI * 1.5
2

To get an slice that was clicked on, getElementAtEvent can be used. Worked for me!

 stackedBar(datasets) { var c = $("#canvas-bar"); var ctx = c[0].getContext("2d"); let __this = this; this.chart = new Chart(ctx, { type: 'bar', data: { labels: ["something"], datasets: datasets, }, options: { onClick: function (e, item) { __this.onClickAction(e, item); }, title: {}, legend: {}, scales: {} } }); } onClickAction(event, elements) { if (elements && elements.length) { let selected = this.chart.getElementAtEvent(event)[0]; let sliceIndex = selected['_datasetIndex']; } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.