Javascript ChartJS 在 X 轴标签中换行 '\n' 或使用 ChartJS V2 在图表或工具提示周围显示更多信息
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37090625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ChartJS New Lines '\n' in X axis Labels or Displaying More Information Around Chart or Tooltip with ChartJS V2
提问by user3878014
I'm using chart.js (V2) to try to build a bar chart that has more information available to user without having to hover over or click anywhere. I've provided two examples of how I hope to edit my chart.
我正在使用 chart.js (V2) 来尝试构建一个条形图,该图为用户提供更多信息,而无需悬停或单击任何地方。我提供了两个我希望如何编辑图表的示例。
Two edited versions of what I hope to achieve
As can be seen, I hope to place (somewhere), some extra information outside of the labels. I had hope that by adding '\n' to the labels I might have been able to get what I was looking for similar to option A.
可以看出,我希望在标签之外放置(某处)一些额外的信息。我曾希望通过在标签中添加 '\n' 可能能够得到我想要的类似于选项 A 的东西。
Some edited code is provided blow:
提供了一些编辑过的代码:
var barChartData = {
labels: playerNames,
datasets: [{
label: 'Actual Score/Hour',
backgroundColor: "rgba(0, 128, 0,0.5)",
data: playerScores
}, {
label: 'Expected Score/Hour',
backgroundColor: "rgba(255,0,0,0.5)",
data: playerExpected
}]
};
function open_win(linktosite) {
window.open(linktosite)
}
canvas.onclick = function(evt){
var activePoints = myBar.getElementsAtEvent(evt);
console.log(activePoints);
linktosite = 'https://www.mytestsite.com/' + activePoints[1]['_model']['label'];
open_win(linktosite);
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
title:{
display:true,
text:"Player Expected and Actual Score per Hour"
},
tooltips: {
mode: 'label'
},
responsive: true,
scales: {
xAxes: [{
stacked: false,
}],
yAxes: [{
stacked: false
}]
},
animation: {
onComplete: function () {
var ctx = this.chart.ctx;
ctx.textAlign = "center";
Chart.helpers.each(this.data.datasets.forEach(function (dataset) {
Chart.helpers.each(dataset.metaData.forEach(function (bar, index) {
// console.log("printing bar" + bar);
ctx.fillText(dataset.data[index], bar._model.x, bar._model.y - 10);
}),this)
}),this);
}
}
}
});
// Chart.helpers.each(myBar.getDatasetMeta(0).data, function(rectangle, index) {
// rectangle.draw = function() {
// myBar.chart.ctx.setLineDash([5, 5]);
// Chart.elements.Rectangle.prototype.draw.apply(this, arguments);
// }
// }, null);
};
At this point I'd be satisfied with having the extradata anywhere on the bar. Any help would be appreciated. Thanks~
在这一点上,我会对在栏上的任何地方拥有额外数据感到满意。任何帮助,将不胜感激。谢谢~
回答by Chris Trevarthen
Chart.js v2.1.5 allows for multi-line labels using nested arrays (v2.5.0 fixes it for radar graphs):
Chart.js v2.1.5 允许使用嵌套数组的多行标签(v2.5.0 修复了雷达图):
...
data: {
labels: [["Jake", "Active: 2 hrs", "Score: 1", "Expected: 127", "Attempts: 4"],
["Matt", "Active: 2 hrs", "Score: 4", "Expected: 36", "Attempts: 4"]],
...
However, this does mean that you will have to pre-calculate the label values.
但是,这确实意味着您必须预先计算标签值。
回答by iorrah
If you are using Chart.js v2.7.1, the above solution might not work.
如果您使用的是 Chart.js v2.7.1,则上述解决方案可能不起作用。
The solution that actually worked for us was adding a small plugin
right in the data
and options
level:
实际上对我们有用的解决方案是plugin
在data
和options
级别中添加一个小权限:
const config = {
type: 'bar',
data: {
// ...
},
options: {
// ...
},
plugins: [{
beforeInit: function (chart) {
chart.data.labels.forEach(function (e, i, a) {
if (/\n/.test(e)) {
a[i] = e.split(/\n/)
}
})
}
}]
};
A full description of how to fix this issue can be found here.
可以在此处找到有关如何解决此问题的完整说明。
回答by SSD
var config = {
type: 'line',
data: {
labels: [["January","First Month","Jellyfish","30 of them"], ["February","Second Month","Foxes","20 of them"], ["March","Third Month","Mosquitoes","None of them"], "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
data: [65, 40, 80, 81, 56, 85, 45],
backgroundColor: "rgba(255,99,132,0.2)",
}, {
label: "My Second dataset",
data: [40, 80, 21, 56, 85, 45, 65],
backgroundColor: "rgba(99,255,132,0.2)",
}]
},
scales : {
xAxes : [{
gridLines : {
display : false,
lineWidth: 1,
zeroLineWidth: 1,
zeroLineColor: '#666666',
drawTicks: false
},
ticks: {
display:true,
stepSize: 0,
min: 0,
autoSkip: false,
fontSize: 11,
padding: 12
}
}],
yAxes: [{
ticks: {
padding: 5
},
gridLines : {
display : true,
lineWidth: 1,
zeroLineWidth: 2,
zeroLineColor: '#666666'
}
}]
},
spanGaps: true,
responsive: true,
maintainAspectRatio: true
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, config);
<div class="myChart">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
</div>
If a label is an array as opposed to a string i.e. [["June","2015"], "July"] then each element is treated as a separate line. The appropriate calculations are made to determine the correct height and width, and rotation is still supported.
如果标签是数组而不是字符串,即 [["June","2015"],"July"] 则每个元素都被视为单独的行。进行适当的计算以确定正确的高度和宽度,并且仍然支持旋转。
charJS version 2.7.2 used this also works in https://github.com/jtblin/angular-chart.js
charJS 版本 2.7.2 使用这也适用于https://github.com/jtblin/angular-chart.js
回答by potatopeelings
With Chart.js v2.1, you can write a chart plugin to do this
使用 Chart.js v2.1,您可以编写图表插件来执行此操作
Preview
预览
Script
脚本
Chart.pluginService.register({
beforeInit: function (chart) {
var hasWrappedTicks = chart.config.data.labels.some(function (label) {
return label.indexOf('\n') !== -1;
});
if (hasWrappedTicks) {
// figure out how many lines we need - use fontsize as the height of one line
var tickFontSize = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontSize, Chart.defaults.global.defaultFontSize);
var maxLines = chart.config.data.labels.reduce(function (maxLines, label) {
return Math.max(maxLines, label.split('\n').length);
}, 0);
var height = (tickFontSize + 2) * maxLines + (chart.options.scales.xAxes[0].ticks.padding || 0);
// insert a dummy box at the bottom - to reserve space for the labels
Chart.layoutService.addBox(chart, {
draw: Chart.helpers.noop,
isHorizontal: function () {
return true;
},
update: function () {
return {
height: this.height
};
},
height: height,
options: {
position: 'bottom',
fullWidth: 1,
}
});
// turn off x axis ticks since we are managing it ourselves
chart.options = Chart.helpers.configMerge(chart.options, {
scales: {
xAxes: [{
ticks: {
display: false,
// set the fontSize to 0 so that extra labels are not forced on the right side
fontSize: 0
}
}]
}
});
chart.hasWrappedTicks = {
tickFontSize: tickFontSize
};
}
},
afterDraw: function (chart) {
if (chart.hasWrappedTicks) {
// draw the labels and we are done!
chart.chart.ctx.save();
var tickFontSize = chart.hasWrappedTicks.tickFontSize;
var tickFontStyle = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
var tickFontFamily = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
var tickLabelFont = Chart.helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
chart.chart.ctx.font = tickLabelFont;
chart.chart.ctx.textAlign = 'center';
var tickFontColor = Chart.helpers.getValueOrDefault(chart.options.scales.xAxes[0].fontColor, Chart.defaults.global.defaultFontColor);
chart.chart.ctx.fillStyle = tickFontColor;
var meta = chart.getDatasetMeta(0);
var xScale = chart.scales[meta.xAxisID];
var yScale = chart.scales[meta.yAxisID];
chart.config.data.labels.forEach(function (label, i) {
label.split('\n').forEach(function (line, j) {
chart.chart.ctx.fillText(line, xScale.getPixelForTick(i + 0.5), (chart.options.scales.xAxes[0].ticks.padding || 0) + yScale.getPixelForValue(yScale.min) +
// move j lines down
j * (chart.hasWrappedTicks.tickFontSize + 2));
});
});
chart.chart.ctx.restore();
}
}
});
and then
进而
...
data: {
labels: ["January\nFirst Month\nJellyfish\n30 of them", "February\nSecond Month\nFoxes\n20 of them", "March\nThird Month\nMosquitoes\nNone of them", "April", "May", "June", "July"],
...
Note - we assume that the maximum content of one line will fit between the ticks (i.e. that no rotation logic is needed. I'm sure it's possible to incorporate rotation logic too, but it would be a tad more complicated)
注意 - 我们假设一行的最大内容将适合刻度之间(即不需要旋转逻辑。我确定也可以合并旋转逻辑,但它会更复杂一点)
You should format the tooltips to not show the x axis label, or format it to show a shorter version of the label.
您应该格式化工具提示以不显示 x 轴标签,或格式化它以显示标签的较短版本。
Fiddle - http://jsfiddle.net/m0q03wpy/