在chartjs 2.0中寻找在"label"元素上添加onClick句柄的方法由于使用以下方法,每当单击Char.js V2.0 RadarChart中的任何一个标签属性时,都会在console.log中返回"未定义"。
var data = {
// below line is the labels
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
datasets: [
{
label: "My First dataset", //this only shows as legend, not label.
backgroundColor: "rgba(179,181,198,0.2)",
borderColor: "rgba(179,181,198,1)",
pointBackgroundColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(179,181,198,1)",
data: [65, 59, 90, 81, 56, 55, 40]
},
....
//Below is how to OnClick on chart points in chart.js V2,
//However, it didn't apply to labels, will return "undifined" .
$('#ChartV2').click(function(e) {
var activePoints = myRadarChart.getElementsAtEvent(e);
var firstPoint = activePoints[0];
console.log(firstPoint);
if (firstPoint !== undefined){
alert(firstPoint._index);
}
});
在chart.js 2.5(可能更早)中,您可以在选项中单击onClick:
'legend' : {
'onClick' : function (evt, item) {
console.log ('legend onClick', evt, item);
},
'display' : true,
'labels' : ...
getElementsAtEvent
只检查图表的main元素(条形图、点、扇区…)。如果您也想考虑标签,则必须重新实现标签的功能。
您需要的大部分代码已经在Chart.js库代码中的不同方法中提供。只需按照以下步骤复制粘贴/清理即可。
脚本
你的点击手应该是
$('#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 label
var 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;
else if (i < halfLabelsCount)
x = pointLabelPosition.x;
else
x = pointLabelPosition.x - width;
if (exactQuarter)
y = pointLabelPosition.y - height / 2;
else if (upperHalf)
y = pointLabelPosition.y - height;
else
y = pointLabelPosition.y
// check if the click was within the bounding box
if ((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/
我为2.8.0版本提出了一个解决方案,将RadialLinear刻度的标签位置计算复制到事件处理程序中。
document.getElementById("myChart").onclick = function (e) {
var helpers = Chart.helpers;
var scale = myRadarChart.scale;
var opts = scale.options;
var tickOpts = opts.ticks;
// Position of click relative to canvas.
var mouseX = e.offsetX;
var mouseY = e.offsetY;
var labelPadding = 5; // number pixels to expand label bounding box by
// get the label render position
// calcs taken from drawPointLabels() in scale.radialLinear.js
var tickBackdropHeight = (tickOpts.display && opts.display) ?
helpers.valueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize)
+ 5: 0;
var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
for (var i = 0; i < scale.pointLabels.length; i++) {
// Extra spacing for top value due to axis labels
var extra = (i === 0 ? tickBackdropHeight / 2 : 0);
var pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + 5);
// get label size info.
// TODO fix width=0 calc in Brave?
// https://github.com/brave/brave-browser/issues/1738
var plSize = scale._pointLabelSizes[i];
// get label textAlign info
var angleRadians = scale.getIndexAngle(i);
var angle = helpers.toDegrees(angleRadians);
var textAlign = 'right';
if (angle == 0 || angle == 180) {
textAlign = 'center';
} else if (angle < 180) {
textAlign = 'left';
}
// get label vertical offset info
// also from drawPointLabels() calcs
var verticalTextOffset = 0;
if (angle === 90 || angle === 270) {
verticalTextOffset = plSize.h / 2;
} else if (angle > 270 || angle < 90) {
verticalTextOffset = plSize.h;
}
// Calculate bounding box based on textAlign
var labelTop = pointLabelPosition.y - verticalTextOffset - labelPadding;
var labelHeight = 2*labelPadding + plSize.h;
var labelBottom = labelTop + labelHeight;
var labelWidth = plSize.w + 2*labelPadding;
var labelLeft;
switch (textAlign) {
case 'center':
var labelLeft = pointLabelPosition.x - labelWidth/2;
break;
case 'left':
var labelLeft = pointLabelPosition.x - labelPadding;
break;
case 'right':
var labelLeft = pointLabelPosition.x - labelWidth + labelPadding;
break;
default:
console.log('ERROR: unknown textAlign '+textAlign);
}
var labelRight = 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 click
if (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在这里:
https://jsfiddle.net/simoncoggins/7r08uLk9/
这种方法的缺点是,如果未来核心标签的实施方式发生变化,它将被打破。如果库将标签位置的计算与其呈现分离,并开始通过API公开位置信息,那会更好。然后,这个解决方案可以大大简化,并且对库的更改更加健壮。
我在这里开了一张票:
https://github.com/chartjs/Chart.js/issues/6549
如果这个问题对你有用,请评论一下。
无法读取未定义的Chartjs 的属性"getDatasetMeta"
如果你从chartjs的doc示例中得到这个错误,那么客户端就是问题所在。将其替换为当前实例的客户端。
在我的情况下,我使用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();
}
myHorizontalBar
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myHorizontalBar = new Chart(ctx, {
type: 'horizontalBar',
data: horizontalBarChartData,
options: {