如何用Chart.js显示折线图数据集点标签?
How to display Line Chart dataset point labels with Chart.js?
我的设计要求是显示包含 5 个趋势数据集的折线图。笔划线上的每个数据值都需要在其各自的数据点显示数据值标签。
不幸的是,我在 Charts.js 中找不到满足此要求的选项。
是否有可以帮助我解决问题的解决方法?
我也在 fiddle 上发布了这个:http://jsfiddle.net/s9eannLh/
非常感谢!
var data = {
labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
datasets: [
{
label: "hemoglobin_1",
title: "test",
fillColor: "transparent",
strokeColor: "#65204c",
pointColor: "#65204c",
pointHighlightStroke: "#FFF",
data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
},
{
label: "hemoglobin_2",
fillColor: "transparent",
strokeColor: "#ed7141",
pointColor: "#ed7141",
pointHighlightStroke: "#FFF",
data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
},
{
label: "hemoglobin_3",
fillColor: "transparent",
strokeColor: "#de4760",
pointColor: "#de4760",
pointHighlightStroke: "#FFF",
data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
},
{
label: "hemoglobin_4",
fillColor: "transparent",
strokeColor: "#fdcf7e",
pointColor: "#fdcf7e",
pointHighlightStroke: "#FFF",
data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
},
{
label: "hemoglobin_5",
fillColor: "transparent",
strokeColor: "#a33a59",
pointColor: "#a33a59",
pointHighlightStroke: "#FFF",
data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
}
]
};
var options = {
responsive: true,
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: 5,
scaleStartValue: 0,
showTooltips: false,
pointDot: true,
pointDotRadius : 6,
datasetStrokeWidth : 3,
bezierCurve : false,
scaleShowHorizontalLines: false,
scaleGridLineWidth : 2,
scaleGridLineColor : "#EEEEEE",
scaleLineWidth: 3,
scaleLineColor: "#000000",
scaleFontFamily: '"Gotham Book",sans-serif',
scaleFontSize: 18
}
var ctx = $("#myChart").get(0).getContext("2d");
var Trends = new Chart(ctx).Line(data, options);
我终于找到了这个问题的答案。
我意识到我可以访问 DOM:
中的图表对象
Trends.datasets
在五个数据集中的每一个中,都有一个包含 x 和 y 位置的点对象:
Trends.datasets[0..4].points
所以我利用 Chart.js:
中的全局配置函数通过回调解析了这些点
// Function - Will fire on animation progression.
onAnimationProgress: function(){},
// Function - Will fire on animation completion.
onAnimationComplete: function(){}
我发现我必须将 onAnimationComplete
与 responsive: true
一起使用,因为点标签会在调整大小事件中消失。
在回调中找到点后,我只需将我想要的标签写到 canvas。
我对代码的补充是:
var options = {
onAnimationProgress: function() { drawDatasetPointsLabels() },
onAnimationComplete: function() { drawDatasetPointsLabels() }
}
新增功能:
function drawDatasetPointsLabels() {
ctx.font = '.9rem "Gotham Book",sans-serif';
ctx.fillStyle = '#AAA';
ctx.textAlign="center";
$(Trends.datasets).each(function(idx,dataset){
$(dataset.points).each(function(pdx,pointinfo){
// First dataset is shifted off the scale line.
// Don't write to the canvas for the null placeholder.
if ( pointinfo.value !== null ) {
ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
}
});
});
}
这里是完整的代码源以及提供解决方案的新代码:
var data = {
labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
datasets: [
{
label: "hemoglobin_1",
fillColor: "transparent",
strokeColor: "#65204c",
pointColor: "#65204c",
pointHighlightStroke: "#FFF",
data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
},
{
label: "hemoglobin_2",
fillColor: "transparent",
strokeColor: "#ed7141",
pointColor: "#ed7141",
pointHighlightStroke: "#FFF",
data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
},
{
label: "hemoglobin_3",
fillColor: "transparent",
strokeColor: "#de4760",
pointColor: "#de4760",
pointHighlightStroke: "#FFF",
data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
},
{
label: "hemoglobin_4",
fillColor: "transparent",
strokeColor: "#fdcf7e",
pointColor: "#fdcf7e",
pointHighlightStroke: "#FFF",
data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
},
{
label: "hemoglobin_5",
fillColor: "transparent",
strokeColor: "#a33a59",
pointColor: "#a33a59",
pointHighlightStroke: "#FFF",
data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
}
]
};
var options = {
responsive: true,
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: 5,
scaleStartValue: 0,
showTooltips: false,
pointDot: true,
pointDotRadius : 6,
datasetStrokeWidth : 3,
bezierCurve : false,
scaleShowHorizontalLines: false,
scaleGridLineWidth : 2,
scaleGridLineColor : "#EEEEEE",
scaleLineWidth: 3,
scaleLineColor: "#000000",
scaleFontFamily: '"Gotham Book",sans-serif',
scaleFontSize: 18,
onAnimationProgress: function() { drawDatasetPointsLabels() },
onAnimationComplete: function() { drawDatasetPointsLabels() }
}
var ctx = $("#myChart").get(0).getContext("2d");
var Trends = new Chart(ctx).Line(data, options);
function drawDatasetPointsLabels() {
ctx.font = '.9rem "Gotham Book",sans-serif';
ctx.fillStyle = '#AAA';
ctx.textAlign="center";
$(Trends.datasets).each(function(idx,dataset){
// First dataset is shifted off the scale line.
// Don't write to the canvas for the null placeholder.
$(dataset.points).each(function(pdx,pointinfo){
if ( pointinfo.value !== null ) {
ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
}
});
});
}
这是 jsfiddle 上有问题的原始版本:http://jsfiddle.net/s9eannLh
[已更新 link]
这是 jsfiddle 上更新的解决方案:https://jsfiddle.net/s9eannLh/82/
谢谢大家!
@JBMcClure 解决方案的更新代码:
var data = {
labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
datasets: [
{
label: "hemoglobin_1",
fillColor: "transparent",
strokeColor: "#65204c",
pointColor: "#65204c",
pointHighlightStroke: "#FFF",
data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
},
{
label: "hemoglobin_2",
fillColor: "transparent",
strokeColor: "#ed7141",
pointColor: "#ed7141",
pointHighlightStroke: "#FFF",
data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
},
{
label: "hemoglobin_3",
fillColor: "transparent",
strokeColor: "#de4760",
pointColor: "#de4760",
pointHighlightStroke: "#FFF",
data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
},
{
label: "hemoglobin_4",
fillColor: "transparent",
strokeColor: "#fdcf7e",
pointColor: "#fdcf7e",
pointHighlightStroke: "#FFF",
data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
},
{
label: "hemoglobin_5",
fillColor: "transparent",
strokeColor: "#a33a59",
pointColor: "#a33a59",
pointHighlightStroke: "#FFF",
data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
}
]
};
var options = {
type: 'line',
data: data,
options: {
responsive: true,
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: 5,
scaleStartValue: 0,
showTooltips: false,
pointDot: true,
pointDotRadius : 6,
datasetStrokeWidth : 3,
bezierCurve : false,
scaleShowHorizontalLines: false,
scaleGridLineWidth : 2,
scaleGridLineColor : "#EEEEEE",
scaleLineWidth: 3,
scaleLineColor: "#000000",
scaleFontFamily: '"Gotham Book",sans-serif',
scaleFontSize: 18,
onAnimationProgress: function() { drawDatasetPointsLabels() },
onAnimationComplete: function() { drawDatasetPointsLabels() }
}
};
var ctx = document.getElementById('myChart').getContext('2d');
var Trends = new Chart(ctx, options);
function drawDatasetPointsLabels() {
ctx.font = '.9rem "Gotham Book",sans-serif';
ctx.fontWeight = 'bold';
ctx.fillStyle = '#AAA';
ctx.textAlign="center";
$(Trends.datasets).each(function(idx,dataset){
$(dataset.points).each(function(pdx,pointinfo){
if ( pointinfo.value !== null ) {
ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
}
});
});
}
@JBMcClure 这是更新后的工作 link:
下面是如何根据 github 上提供的示例进行操作。它看起来与您的解决方案相似...
// Define a plugin to provide data labels
Chart.plugins.register({
afterDatasetsDraw: function(chart, easing) {
// To only draw at the end of animation, check for easing === 1
var ctx = chart.ctx;
chart.data.datasets.forEach(function (dataset, i) {
var meta = chart.getDatasetMeta(i);
if (!meta.hidden) {
meta.data.forEach(function(element, index) {
// Draw the text in black, with the specified font
ctx.fillStyle = 'rgb(0, 0, 0)';
var fontSize = 16;
var fontStyle = 'normal';
var fontFamily = 'Helvetica Neue';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
// Just naively convert to string for now
var dataString = dataset.data[index].toString();
// Make sure alignment settings are correct
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var padding = 5;
var position = element.tooltipPosition();
ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);
});
}
});
}
});
来自代码:
https://github.com/chartjs/Chart.js/blob/master/samples/advanced/data-labelling.html
示例:
http://www.chartjs.org/samples/latest/advanced/data-labelling.html
您还可以定义图表内联插件而不是全局...
var chart = new Chart(ctx, {
plugins: [{
afterDatasetsDraw: ...
}]
});
如果有人像我最近一样来这里寻找这个,这里有一个新插件可用。
我的设计要求是显示包含 5 个趋势数据集的折线图。笔划线上的每个数据值都需要在其各自的数据点显示数据值标签。
不幸的是,我在 Charts.js 中找不到满足此要求的选项。
是否有可以帮助我解决问题的解决方法?
我也在 fiddle 上发布了这个:http://jsfiddle.net/s9eannLh/
非常感谢!
var data = {
labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
datasets: [
{
label: "hemoglobin_1",
title: "test",
fillColor: "transparent",
strokeColor: "#65204c",
pointColor: "#65204c",
pointHighlightStroke: "#FFF",
data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
},
{
label: "hemoglobin_2",
fillColor: "transparent",
strokeColor: "#ed7141",
pointColor: "#ed7141",
pointHighlightStroke: "#FFF",
data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
},
{
label: "hemoglobin_3",
fillColor: "transparent",
strokeColor: "#de4760",
pointColor: "#de4760",
pointHighlightStroke: "#FFF",
data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
},
{
label: "hemoglobin_4",
fillColor: "transparent",
strokeColor: "#fdcf7e",
pointColor: "#fdcf7e",
pointHighlightStroke: "#FFF",
data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
},
{
label: "hemoglobin_5",
fillColor: "transparent",
strokeColor: "#a33a59",
pointColor: "#a33a59",
pointHighlightStroke: "#FFF",
data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
}
]
};
var options = {
responsive: true,
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: 5,
scaleStartValue: 0,
showTooltips: false,
pointDot: true,
pointDotRadius : 6,
datasetStrokeWidth : 3,
bezierCurve : false,
scaleShowHorizontalLines: false,
scaleGridLineWidth : 2,
scaleGridLineColor : "#EEEEEE",
scaleLineWidth: 3,
scaleLineColor: "#000000",
scaleFontFamily: '"Gotham Book",sans-serif',
scaleFontSize: 18
}
var ctx = $("#myChart").get(0).getContext("2d");
var Trends = new Chart(ctx).Line(data, options);
我终于找到了这个问题的答案。
我意识到我可以访问 DOM:
中的图表对象Trends.datasets
在五个数据集中的每一个中,都有一个包含 x 和 y 位置的点对象:
Trends.datasets[0..4].points
所以我利用 Chart.js:
中的全局配置函数通过回调解析了这些点 // Function - Will fire on animation progression.
onAnimationProgress: function(){},
// Function - Will fire on animation completion.
onAnimationComplete: function(){}
我发现我必须将 onAnimationComplete
与 responsive: true
一起使用,因为点标签会在调整大小事件中消失。
在回调中找到点后,我只需将我想要的标签写到 canvas。
我对代码的补充是:
var options = {
onAnimationProgress: function() { drawDatasetPointsLabels() },
onAnimationComplete: function() { drawDatasetPointsLabels() }
}
新增功能:
function drawDatasetPointsLabels() {
ctx.font = '.9rem "Gotham Book",sans-serif';
ctx.fillStyle = '#AAA';
ctx.textAlign="center";
$(Trends.datasets).each(function(idx,dataset){
$(dataset.points).each(function(pdx,pointinfo){
// First dataset is shifted off the scale line.
// Don't write to the canvas for the null placeholder.
if ( pointinfo.value !== null ) {
ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
}
});
});
}
这里是完整的代码源以及提供解决方案的新代码:
var data = {
labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
datasets: [
{
label: "hemoglobin_1",
fillColor: "transparent",
strokeColor: "#65204c",
pointColor: "#65204c",
pointHighlightStroke: "#FFF",
data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
},
{
label: "hemoglobin_2",
fillColor: "transparent",
strokeColor: "#ed7141",
pointColor: "#ed7141",
pointHighlightStroke: "#FFF",
data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
},
{
label: "hemoglobin_3",
fillColor: "transparent",
strokeColor: "#de4760",
pointColor: "#de4760",
pointHighlightStroke: "#FFF",
data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
},
{
label: "hemoglobin_4",
fillColor: "transparent",
strokeColor: "#fdcf7e",
pointColor: "#fdcf7e",
pointHighlightStroke: "#FFF",
data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
},
{
label: "hemoglobin_5",
fillColor: "transparent",
strokeColor: "#a33a59",
pointColor: "#a33a59",
pointHighlightStroke: "#FFF",
data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
}
]
};
var options = {
responsive: true,
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: 5,
scaleStartValue: 0,
showTooltips: false,
pointDot: true,
pointDotRadius : 6,
datasetStrokeWidth : 3,
bezierCurve : false,
scaleShowHorizontalLines: false,
scaleGridLineWidth : 2,
scaleGridLineColor : "#EEEEEE",
scaleLineWidth: 3,
scaleLineColor: "#000000",
scaleFontFamily: '"Gotham Book",sans-serif',
scaleFontSize: 18,
onAnimationProgress: function() { drawDatasetPointsLabels() },
onAnimationComplete: function() { drawDatasetPointsLabels() }
}
var ctx = $("#myChart").get(0).getContext("2d");
var Trends = new Chart(ctx).Line(data, options);
function drawDatasetPointsLabels() {
ctx.font = '.9rem "Gotham Book",sans-serif';
ctx.fillStyle = '#AAA';
ctx.textAlign="center";
$(Trends.datasets).each(function(idx,dataset){
// First dataset is shifted off the scale line.
// Don't write to the canvas for the null placeholder.
$(dataset.points).each(function(pdx,pointinfo){
if ( pointinfo.value !== null ) {
ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
}
});
});
}
这是 jsfiddle 上有问题的原始版本:http://jsfiddle.net/s9eannLh
[已更新 link] 这是 jsfiddle 上更新的解决方案:https://jsfiddle.net/s9eannLh/82/
谢谢大家!
@JBMcClure 解决方案的更新代码:
var data = {
labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
datasets: [
{
label: "hemoglobin_1",
fillColor: "transparent",
strokeColor: "#65204c",
pointColor: "#65204c",
pointHighlightStroke: "#FFF",
data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
},
{
label: "hemoglobin_2",
fillColor: "transparent",
strokeColor: "#ed7141",
pointColor: "#ed7141",
pointHighlightStroke: "#FFF",
data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
},
{
label: "hemoglobin_3",
fillColor: "transparent",
strokeColor: "#de4760",
pointColor: "#de4760",
pointHighlightStroke: "#FFF",
data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
},
{
label: "hemoglobin_4",
fillColor: "transparent",
strokeColor: "#fdcf7e",
pointColor: "#fdcf7e",
pointHighlightStroke: "#FFF",
data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
},
{
label: "hemoglobin_5",
fillColor: "transparent",
strokeColor: "#a33a59",
pointColor: "#a33a59",
pointHighlightStroke: "#FFF",
data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
}
]
};
var options = {
type: 'line',
data: data,
options: {
responsive: true,
scaleOverride: true,
scaleSteps: 10,
scaleStepWidth: 5,
scaleStartValue: 0,
showTooltips: false,
pointDot: true,
pointDotRadius : 6,
datasetStrokeWidth : 3,
bezierCurve : false,
scaleShowHorizontalLines: false,
scaleGridLineWidth : 2,
scaleGridLineColor : "#EEEEEE",
scaleLineWidth: 3,
scaleLineColor: "#000000",
scaleFontFamily: '"Gotham Book",sans-serif',
scaleFontSize: 18,
onAnimationProgress: function() { drawDatasetPointsLabels() },
onAnimationComplete: function() { drawDatasetPointsLabels() }
}
};
var ctx = document.getElementById('myChart').getContext('2d');
var Trends = new Chart(ctx, options);
function drawDatasetPointsLabels() {
ctx.font = '.9rem "Gotham Book",sans-serif';
ctx.fontWeight = 'bold';
ctx.fillStyle = '#AAA';
ctx.textAlign="center";
$(Trends.datasets).each(function(idx,dataset){
$(dataset.points).each(function(pdx,pointinfo){
if ( pointinfo.value !== null ) {
ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
}
});
});
}
@JBMcClure 这是更新后的工作 link:
下面是如何根据 github 上提供的示例进行操作。它看起来与您的解决方案相似...
// Define a plugin to provide data labels
Chart.plugins.register({
afterDatasetsDraw: function(chart, easing) {
// To only draw at the end of animation, check for easing === 1
var ctx = chart.ctx;
chart.data.datasets.forEach(function (dataset, i) {
var meta = chart.getDatasetMeta(i);
if (!meta.hidden) {
meta.data.forEach(function(element, index) {
// Draw the text in black, with the specified font
ctx.fillStyle = 'rgb(0, 0, 0)';
var fontSize = 16;
var fontStyle = 'normal';
var fontFamily = 'Helvetica Neue';
ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);
// Just naively convert to string for now
var dataString = dataset.data[index].toString();
// Make sure alignment settings are correct
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var padding = 5;
var position = element.tooltipPosition();
ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);
});
}
});
}
});
来自代码: https://github.com/chartjs/Chart.js/blob/master/samples/advanced/data-labelling.html
示例: http://www.chartjs.org/samples/latest/advanced/data-labelling.html
您还可以定义图表内联插件而不是全局...
var chart = new Chart(ctx, {
plugins: [{
afterDatasetsDraw: ...
}]
});
如果有人像我最近一样来这里寻找这个,这里有一个新插件可用。