I would like to ask if it's possible using Chart.js to display data values? I want to print the graph.
Thanks for any advice.
This question is related to
javascript
chart.js
If you are using the plugin chartjs-plugin-datalabels then the following code options object will help
Make sure you import import 'chartjs-plugin-datalabels';
in your typescript file or add reference to <script src="chartjs-plugin-datalabels.js"></script>
in your javascript file.
options: {
maintainAspectRatio: false,
responsive: true,
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
}
}]
},
plugins: {
datalabels: {
anchor: 'end',
align: 'top',
formatter: Math.round,
font: {
weight: 'bold'
}
}
}
}
Following this good answer, I'd use these options for a bar chart:
var chartOptions = {
animation: false,
responsive : true,
tooltipTemplate: "<%= value %>",
tooltipFillColor: "rgba(0,0,0,0)",
tooltipFontColor: "#444",
tooltipEvents: [],
tooltipCaretSize: 0,
onAnimationComplete: function()
{
this.showTooltip(this.datasets[0].bars, true);
}
};
window.myBar = new Chart(ctx1).Bar(chartData, chartOptions);
This still uses the tooltip system and his advantages (automatic positionning, templating, ...) but hiding the decorations (background color, caret, ...)
Based on @Ross's answer answer for Chart.js 2.0 and up, I had to include a little tweak to guard against the case when the bar's heights comes too chose to the scale boundary.
The animation
attribute of the bar chart's option:
animation: {
duration: 500,
easing: "easeOutQuart",
onComplete: function () {
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
scale_max = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
ctx.fillStyle = '#444';
var y_pos = model.y - 5;
// Make sure data value does not get overflown and hidden
// when the bar's value is too close to max value of scale
// Note: The y value is reverse, it counts from top down
if ((scale_max - model.y) / scale_max >= 0.93)
y_pos = model.y + 20;
ctx.fillText(dataset.data[i], model.x, y_pos);
}
});
}
}
From my experience, once you include the chartjs-plugin-datalabels plugin (make sure to place the <script>
tag after the chart.js tag on your page), your charts begin to display values.
If you then choose you can customize it to fit your needs. The customization is clearly documented here but basically, the format is like this hypothetical example:
var myBarChart = new Chart(ctx, {
type: 'bar',
data: yourDataObject,
options: {
// other options
plugins: {
datalabels: {
anchor :'end',
align :'top',
// and if you need to format how the value is displayed...
formatter: function(value, context) {
return GetValueFormatted(value);
}
}
}
}
});
This animation option works for 2.1.3 on a bar chart.
Slightly modified @Ross answer
animation: {
duration: 0,
onComplete: function () {
// render the value of the chart above the bar
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.fillStyle = this.chart.config.options.defaultFontColor;
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
ctx.fillText(dataset.data[i], model.x, model.y - 5);
}
});
}}
I'd recommend using this plugin: https://github.com/chartjs/chartjs-plugin-datalabels
Labels can be added to your charts simply by importing the plugin to the js file e.g.:
import 'chartjs-plugin-datalabels'
And can be fine tuned using these docs: https://chartjs-plugin-datalabels.netlify.com/options.html
I think the nicest option to do this in chartJS v2.x is by using a plugin, so you don't have a large block of code in the options. In addition, it prevents the data from disappearing when hovering over a bar.
I.e. simply use this code, which registers a plugin that adds the text after the chart is drawn.
Chart.pluginService.register({
afterDraw: function(chartInstance) {
var ctx = chartInstance.chart.ctx;
// render the value of the chart above the bar
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
chartInstance.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
ctx.fillText(dataset.data[i], model.x, model.y - 2);
}
});
}
});
From chart.js samples (file Chart.js-2.4.0/samples/data_labelling.html) :
``` // Define a plugin to provide data labels
Chart.plugins.register({
afterDatasetsDraw: function(chartInstance, easing) {
// To only draw at the end of animation, check for easing === 1
var ctx = chartInstance.chart.ctx;
chartInstance.data.datasets.forEach(function (dataset, i) {
var meta = chartInstance.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);
});
}
});
}
});
```
Edited @ajhuddy's answer a little. Only for bar charts. My version adds:
Downside: When hovering over a bar that has value inside it the value might look a little jagged. I have not found a solution do disable hover effects. It might also need tweaking depending on your own settings.
Configuration:
bar: {
tooltips: {
enabled: false
},
hover: {
animationDuration: 0
},
animation: {
onComplete: function() {
this.chart.controller.draw();
drawValue(this, 1);
},
onProgress: function(state) {
var animation = state.animationObject;
drawValue(this, animation.currentStep / animation.numSteps);
}
}
}
Helpers:
// Font color for values inside the bar
var insideFontColor = '255,255,255';
// Font color for values above the bar
var outsideFontColor = '0,0,0';
// How close to the top edge bar can be before the value is put inside it
var topThreshold = 20;
var modifyCtx = function(ctx) {
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
return ctx;
};
var fadeIn = function(ctx, obj, x, y, black, step) {
var ctx = modifyCtx(ctx);
var alpha = 0;
ctx.fillStyle = black ? 'rgba(' + outsideFontColor + ',' + step + ')' : 'rgba(' + insideFontColor + ',' + step + ')';
ctx.fillText(obj, x, y);
};
var drawValue = function(context, step) {
var ctx = context.chart.ctx;
context.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
var textY = (model.y > topThreshold) ? model.y - 3 : model.y + 20;
fadeIn(ctx, dataset.data[i], model.x, textY, model.y > topThreshold, step);
}
});
};
Here is an updated version for Chart.js 2.3
Sep 23, 2016: Edited my code to work with v2.3 for both line/bar type.
Important: Even if you don't need the animation, don't change the duration option to 0, otherwise you will get chartInstance.controller is undefined error.
var chartData = {_x000D_
labels: ["January", "February", "March", "April", "May", "June"],_x000D_
datasets: [_x000D_
{_x000D_
fillColor: "#79D1CF",_x000D_
strokeColor: "#79D1CF",_x000D_
data: [60, 80, 81, 56, 55, 40]_x000D_
}_x000D_
]_x000D_
};_x000D_
_x000D_
var opt = {_x000D_
events: false,_x000D_
tooltips: {_x000D_
enabled: false_x000D_
},_x000D_
hover: {_x000D_
animationDuration: 0_x000D_
},_x000D_
animation: {_x000D_
duration: 1,_x000D_
onComplete: function () {_x000D_
var chartInstance = this.chart,_x000D_
ctx = chartInstance.ctx;_x000D_
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);_x000D_
ctx.textAlign = 'center';_x000D_
ctx.textBaseline = 'bottom';_x000D_
_x000D_
this.data.datasets.forEach(function (dataset, i) {_x000D_
var meta = chartInstance.controller.getDatasetMeta(i);_x000D_
meta.data.forEach(function (bar, index) {_x000D_
var data = dataset.data[index]; _x000D_
ctx.fillText(data, bar._model.x, bar._model.y - 5);_x000D_
});_x000D_
});_x000D_
}_x000D_
}_x000D_
};_x000D_
var ctx = document.getElementById("Chart1"),_x000D_
myLineChart = new Chart(ctx, {_x000D_
type: 'bar',_x000D_
data: chartData,_x000D_
options: opt_x000D_
});
_x000D_
<canvas id="myChart1" height="300" width="500"></canvas>
_x000D_
Source: Stackoverflow.com