How do I fix over limit y axis value in ChartJS - javascript

Hello Everyone!
I am using chartjs-plugin-datalabels to prevent unhoverable tiny values by displaying the value above his bar, but when one of them has the highest value the datalabels exceed the limit of the chart container
UPDATE:
Also, you can use suggestedMax option and I think it's better than giving a padding
const options = {
plugins: {
datalabels: {
color: '#374774',
font: { family: 'MyriadSemiBold', size: 14 },
align: 'end',
anchor: 'end',
formatter: (value) => {
if (value > 0) {
return localizeNumber(value)
}
return ''
},
},
legend: { display: false },
},
scales: {
x: {
grid: { lineWidth: 0 },
ticks: {
display: false,
},
},
y: {
// Highest value in your datasets
suggestedMax: highestValue > 0 ? highestValue + 1e5 : 10,
grid: { color: '#DFDFDF' },
ticks: {
callback: (value) => {
return abbreviateNumber(value)
},
font: { family: 'MyriadRegular', size: 14 },
color: '#374774',
},
},
},
}

The easiest solution is to add padding to the top of your chart (simple sample below). You may also play around with the datalabel plugin's clamping options to adjust the position of the label when it's outside the chart.
const layoutOptions = {
padding: {
top: 30 // Add 30 pixels of padding to top of chart.
}
};
const data = {
labels: ['Large', 'Small'],
datasets: [{ data: [100, 2] }]
};
const config = {
type: 'bar',
data: data,
options: {
layout: layoutOptions,
scales: { y: { beginAtZero: true, max: 100 } },
plugins: {
legend: { display: false },
datalabels: { anchor: 'end', align: 'top' }
}
},
};
new Chart(document.getElementById('myChart'), config);
#myChart {
max-height: 180px;
}
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#2.0.0"></script>
<script>Chart.register(ChartDataLabels);</script>

Related

Chart-Js x-axis becomes jumbled

I need to retrieve multiple datapoints from my JSON file and display them on the graph. However, it becomes jumbled around the x-axis, and becomes thin. How do I space these out?
I have
Graph
[
const config = {
type: 'bar',
data,
options: {
scales: {
y: {
beginAtZero: true,
padding: 50
},
x: {
offset: true,
ticks: {
stepSize: 50,
fixedStepSize: 50,
}
}
},
plugins: {
title: {
display: true,
text: 'Worm Egg Count'
},
}
}
};
]2

How to use excess vertical space in stacked bar chart?

I am trying to create a stacked bar chart (with chart.js 3.7+) which uses the entire canvas:
new Chart(..., {
type: 'bar',
data: {
labels: ['a','b','c','d','e'],
datasets: [{
backgroundColor: '#ff00ff',
data: [20,40,60,40,20],
},{
backgroundColor: '#00ff00',
data: [100,200,300,200,100],
}]
},
options: {
maintainAspectRatio: false,
responsive: true,
plugins: {
legend: { display: false },
},
scales: {
x: {
display: false,
stacked: true
},
y: {
display: true,
stacked: true
}
}
}
});
When I use a normal bar chart the graph is stretched to use up all the vertical space:
But when I stack the bars the combined longest bar doesn't use up all the vertical space:
How can I get the stacked bar chart to stretch to use all available vertical space?
See example here.
You could sum your arrays, find the max value in the resulting array and set the options.scales.y.max property with this value :
let data1 = [20,40,60,40,20];
let data2 = [100,200,300,200,100];
let sum = data1.map(function (num, idx) {
return num + data2[idx];
});
let max = Math.max(...sum);
var options =
{
maintainAspectRatio: false,
responsive: true,
plugins: {
legend: { display: false },
},
scales: {
x: {
display: false,
stacked: true
},
y: {
display: true,
stacked: true,
max: max
}
}
};
var mychart = new Chart(document.getElementById('mycanvas2').getContext('2d'), {
type: 'bar',
data: {
labels: ['a','b','c','d','e'],
datasets: [{
backgroundColor: '#ff00ff',
data: data1
},{
backgroundColor: '#00ff00',
data: data2
}]
},
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
<div style="width:400px; height: 200px">
<canvas id="mycanvas2"></canvas>
</div>
According to this issue with chart.js you can configure the y-axis bounds to fit the data:
options: {
scales: {
x: {
display: false,
stacked: true
},
y: {
display: true,
stacked: true,
bounds: 'data' <----------
}
}
}

Data Labels wrongly positioned on bar chart - chartjs

I'm using chartjs-plugin-datalabels to show values on chart, but the labels are not centered.
The main part is in the datasets.datalabels where I can override default settings, which sets to center anyway, but wanted to show where its done.
I have tried positione it to the right, but as the value getting bigger, the datalabel is less centered.
Chart.register(ChartDataLabels);
const data_tafkidim_cat_count = {
labels: window.TafkidimCatCount.map((el) => el.TafkidCat.split(' ')).slice(0, pagination['tafkidim_cat_count'].show),
datasets: [
{
data: window.TafkidimCatCount.map((el) => el.Total),
backgroundColor: Setcolors(),
borderColor: Setcolors(1),
borderWidth: 1,
datalabels: {
anchor: 'center',
align: 'center',
},
},
],
};
const config_tafkidim_cat_count = {
type: 'bar',
data: data_tafkidim_cat_count,
options: {
scales: {
x: {
grid: {
borderColor: '#829AB1',
},
ticks: {
color: '#627D98',
},
reverse: true,
},
y: {
grid: {
borderColor: '#829AB1',
},
beginAtZero: true,
ticks: {
color: '#627D98',
},
},
},
plugins: {
title: {
text: TL['tafkidim_cat_count'],
padding: {
bottom: 20,
},
},
legend: {
display: false,
},
tooltip: {
callbacks: {
title: (context) => {
return context[0].label.replaceAll(',', ' ');
},
},
},
},
},
};
const tafkidim_cat_count = new Chart('#tafkidim-cat-count'.Element().getContext('2d'), config_tafkidim_cat_count);
solved it with
textAlign = "center"
apparently the default is "start".

How to show thousand in k format for bar values in chart.js

I have many bars with a thousand values like 35000, 12000, and 76560. So these values are getting overlapped with each other. I need to change Bar values not StepSize.
I want to show these values 35k, 12k and 76.5k format. This is my code
public barStatus() {
var colors = ['#299DFF', '#80FFFF', '#F8362B', ];
var chBar = document.getElementById("chBar");
var chartData = {
datasets: [{
label: 'Success',
data: [35000, 12000, 76560],
backgroundColor: colors[0]
}, ]
}
var barOptions_stacked = {
onClick: this.Status,
tooltips: {
enabled: true
},
plugins: {
datalabels: {
anchor: 'end',
align: 'left',
formatter: Math.round,
font: {
color: 'black'
}
},
},
hover: {
animationDuration: 0
},
scales: {
xAxes: [{
barPercentage: 0.5,
categoryPercentage: 0.5
}
],
yAxes: [{
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function (value, index, values) {
return Number(value.toString()); //pass tick values as a string into Number function
}
},
afterBuildTicks: function (chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
},
stacked: false
}]
},
};
this.Canvas = document.getElementById("chBar");
this.chart = new Chart(this.Canvas, {
type: "bar",
data: chartData,
options: barOptions_stacked
});
}
How can I do that?
Screenshot:
You need to pass a function in formatter option inside datalabels plugin configuration:
datalabels: {
anchor: "end",
align: "left",
formatter: function(context) {
return context / 1000 + "k";
},
font: {
color: "black"
}
}
You can check the solution in this demo: https://stackblitz.com/edit/angular-chart-js-thousand?file=src/app/app.component.ts
For styling only the labels you want something like this:
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: "# of Votes",
data: [12000, 1900, 3000, 5000, 2201, 3492]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
setTimeout(function() {
myChart.options.scales = {
xAxes: [],
yAxes: [{
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function(value, index, values) {
return Number((value / 1000).toString()) + 'K'; //pass tick values as a string into Number function
}
},
afterBuildTicks: function(chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
}
}]
};
myChart.update();
}, 1000);
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.js"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
In case you want to change the format of the value shown when hovering the chart and displaying the value inside the tooltip, you need to use the tooltip callbacks.
For example:
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "# of Votes",
data: [12000, 1900, 3000, 5000, 2201, 3492]
}
]
},
options: {
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return (tooltipItem.yLabel/1000)+'K';
}
}
},
scales: {
yAxes: [
{
ticks: {
beginAtZero: true
}
}
]
}
}
});
setTimeout(function() {
myChart.options.scales = {
xAxes: [],
yAxes: [ {
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function (value, index, values) {
return Number((value/1000).toString())+'K'; //pass tick values as a string into Number function
}
},
afterBuildTicks: function (chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
}
}
]
};
myChart.update();
}, 1000);
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.js"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
Last example involves the plugin you use in your question.
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: "line",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
datalabels: {
color: '#000'
},
label: "# of Votes",
data: [12000, 1900, 3000, 5000, 2201, 3492]
}]
},
options: {
plugins: {
datalabels: {
color: '#000',
formatter: function(value, context) {
return context.chart.data.labels[context.dataIndex] + ': ' + Math.round(value / 1000) + 'K';
}
}
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
return (tooltipItem.yLabel / 1000) + 'K';
}
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
setTimeout(function() {
myChart.options.scales = {
xAxes: [],
yAxes: [{
gridLines: {
display: false
},
type: 'logarithmic',
position: 'left',
ticks: {
min: 0, //minimum tick
max: 100000, //maximum tick
callback: function(value, index, values) {
return Number((value / 1000).toString()) + 'K'; //pass tick values as a string into Number function
}
},
afterBuildTicks: function(chartObj) { //Build ticks labelling as per your need
chartObj.ticks = [];
chartObj.ticks.push(0);
chartObj.ticks.push(10);
chartObj.ticks.push(100);
chartObj.ticks.push(1000);
chartObj.ticks.push(10000);
chartObj.ticks.push(100000);
},
scaleLabel: {
display: false
}
}]
};
myChart.update();
}, 1000);
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/Chart.bundle.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
I have found the solution (just now). In config option its will have animation and call back with function onComplete. Here you can draw the label with any format you want. Please see this picture for code

Changing fontFamily on ChartJS bar chart

I've partially implemented ChartJS in a project, but I can't figure out how to change the font that's displayed on the X and Y axes of a bar chart.
I've read the ChartJS documentation, searched for examples on GitHub, etc. I'm not sure what I'm doing wrong, but I rest assured knowing the solution will involve a line of code and will be a startlingly stupid oversight on my part.
This code draws the chart I want, but with the default font:
var barChartLanguage = Chart.Bar(myCanvas, {
data: dataLanguages,
options: options,
defaults: defaults
});
I tried changing the font in the defaults without success:
var defaults = {
global: {
// example font
defaultFontFamily: "'Raleway'"
}
};
And I tried changing it on the axis with options:
var options = {
animation: {
duration: 2000
},
scales: {
yAxes: [{
display: true,
ticks: {
suggestedMin: 0, // minimum will be 0, unless there is a lower value.
// OR //
beginAtZero: true, // minimum value will be 0.
suggestedMax: 10
},
gridLines: {
display: false
},
pointLabels: {
fontFamily: "'Raleway'"
}
}],
xAxes: [{
gridLines: {
display: false
}
}],
},
};
Add ticks.fontFamily to xAxes so it will look like this:
xAxes: [{
gridLines: {
display: false
},
ticks: {
fontFamily: "Verdana",
}
}],
Documentation: http://www.chartjs.org/docs/#scales
Example on jsfiddle: http://jsfiddle.net/4asLpwd5/
From version 3.x, onwards the syntax was changed.
Chart.js migration guide: 3.x Migration Guide
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: chartData,
options: {
responsive: true,
plugins: {
legend: {
display: false,
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
font: {
family: 'Raleway', // Your font family
size: 14,
},
},
},
y: {
beginAtZero: true,
ticks: {
font: {
family: 'Raleway', // Your font family
size: 14,
},
// Include a dollar sign in the ticks
callback: function (value, index, values) {
return '$' + value;
},
},
}
}
}
});

Categories