How To Add Onclick Event On Labels In Chart.js V2.0?
Solution 1:
in chart.js 2.5 (maybe even earlier) you can put an onClick in the options:
'legend' : {
'onClick' : function (evt, item) {
console.log ('legend onClick', evt, item);
},
'display' : true,
'labels' : ...
Solution 2:
getElementsAtEvent
checks only the main elements of the chart (bars, points, sectors...). If you want to consider labels too, you'll have to reimplement the functionality for labels.
Most of the code you need is already available in different methods in the Chart.js library code. Just copy-paste / cleanup as done below.
Script
Your click hander should be
$('#myChart').click(function (e) {
var helpers = Chart.helpers;
var eventPosition = helpers.getRelativePosition(e, myRadarChart.chart);
var mouseX = eventPosition.x;
var mouseY = eventPosition.y;
var activePoints = [];
// loop through all the labels
helpers.each(myRadarChart.scale.ticks, function (label, index) {
for (var i = this.getValueCount() - 1; i >= 0; i--) {
// here we effectively get the bounding box for each labelvar pointLabelPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max) + 5);
var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, Chart.defaults.global.defaultFontSize);
var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, Chart.defaults.global.defaultFontStyle);
var pointLabeFontFamily = helpers.getValueOrDefault(this.options.pointLabels.fontFamily, Chart.defaults.global.defaultFontFamily);
var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
ctx.font = pointLabeFont;
var labelsCount = this.pointLabels.length,
halfLabelsCount = this.pointLabels.length / 2,
quarterLabelsCount = halfLabelsCount / 2,
upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
var width = ctx.measureText(this.pointLabels[i]).width;
var height = pointLabelFontSize;
var x, y;
if (i === 0 || i === halfLabelsCount)
x = pointLabelPosition.x - width / 2;
elseif (i < halfLabelsCount)
x = pointLabelPosition.x;
else
x = pointLabelPosition.x - width;
if (exactQuarter)
y = pointLabelPosition.y - height / 2;
elseif (upperHalf)
y = pointLabelPosition.y - height;
else
y = pointLabelPosition.y
// check if the click was within the bounding boxif ((mouseY >= y && mouseY <= y + height) && (mouseX >= x && mouseX <= x + width))
activePoints.push({ index: i, label: this.pointLabels[i] });
}
}, myRadarChart.scale);
var firstPoint = activePoints[0];
if (firstPoint !== undefined) {
alert(firstPoint.index + ': ' + firstPoint.label);
}
});
Fiddle - http://jsfiddle.net/1Lngmtz7/
Solution 3:
I came up with a solution for this for version 2.8.0 by copying the label position calculations from the RadialLinear scale into an event handler.
document.getElementById("myChart").onclick = function (e) {
varhelpers= Chart.helpers;
varscale= myRadarChart.scale;
varopts= scale.options;
vartickOpts= opts.ticks;
// Position of click relative to canvas.varmouseX= e.offsetX;
varmouseY= e.offsetY;
varlabelPadding=5; // number pixels to expand label bounding box by// get the label render position// calcs taken from drawPointLabels() in scale.radialLinear.jsvartickBackdropHeight= (tickOpts.display && opts.display) ?
helpers.valueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize)
+ 5: 0;
varouterDistance= scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
for (vari=0; i < scale.pointLabels.length; i++) {
// Extra spacing for top value due to axis labelsvarextra= (i === 0 ? tickBackdropHeight / 2 : 0);
varpointLabelPosition= scale.getPointPosition(i, outerDistance + extra + 5);
// get label size info.// TODO fix width=0 calc in Brave?// https://github.com/brave/brave-browser/issues/1738varplSize= scale._pointLabelSizes[i];
// get label textAlign infovarangleRadians= scale.getIndexAngle(i);
varangle= helpers.toDegrees(angleRadians);
vartextAlign='right';
if (angle == 0 || angle == 180) {
textAlign = 'center';
} elseif (angle < 180) {
textAlign = 'left';
}
// get label vertical offset info// also from drawPointLabels() calcsvarverticalTextOffset=0;
if (angle === 90 || angle === 270) {
verticalTextOffset = plSize.h / 2;
} elseif (angle > 270 || angle < 90) {
verticalTextOffset = plSize.h;
}
// Calculate bounding box based on textAlignvarlabelTop= pointLabelPosition.y - verticalTextOffset - labelPadding;
varlabelHeight=2*labelPadding + plSize.h;
varlabelBottom= labelTop + labelHeight;
varlabelWidth= plSize.w + 2*labelPadding;
var labelLeft;
switch (textAlign) {
case'center':
varlabelLeft= pointLabelPosition.x - labelWidth/2;
break;
case'left':
varlabelLeft= pointLabelPosition.x - labelPadding;
break;
case'right':
varlabelLeft= pointLabelPosition.x - labelWidth + labelPadding;
break;
default:
console.log('ERROR: unknown textAlign '+textAlign);
}
varlabelRight= labelLeft + labelWidth;
// Render a rectangle for testing purposes
ctx.save();
ctx.strokeStyle = 'red';
ctx.lineWidth = 1;
ctx.strokeRect(labelLeft, labelTop, labelWidth, labelHeight);
ctx.restore();
// compare to the current clickif (mouseX >= labelLeft && mouseX <= labelRight && mouseY <= labelBottom && mouseY >= labelTop) {
alert(scale.pointLabels[i]+' clicked');
// Break loop to prevent multiple clicks, if they overlap we take the first one.break;
}
}
};
JSFiddle here:
https://jsfiddle.net/simoncoggins/7r08uLk9/
The downside of this approach is it that it will break if the core labelling implementation changes in the future. It would be better if the library separated the calculation of label position from its rendering and started exposing the position info via the API. Then this solution could be greatly simplified and would be more robust to library changes.
I've opened a ticket offering to make that change here:
https://github.com/chartjs/Chart.js/issues/6549
Please comment on that issue if it would be useful to you.
Solution 4:
Cannot read property 'getDatasetMeta' of undefined Chartjs
If you got this error from doc example of chartjs, the client is the problem. Replace it with the client of your current instance.
In my case im using myHorizontalBar
var defaultLegendClickHandler = function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = window.myHorizontalBar; //this.chart;var meta = ci.getDatasetMeta(index);
// See controller.isDatasetVisible comment
meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
// We hid a dataset ... rerender the chart
ci.update();
}
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myHorizontalBar = newChart(ctx, {
type: 'horizontalBar',
data: horizontalBarChartData,
options: {
Post a Comment for "How To Add Onclick Event On Labels In Chart.js V2.0?"