Chart JS display Data Value on the top of the Bar - javascript

I m begginning with CHART JS and i've got a problem when i want to display the data Value on the top of each bar and the value disappear when my mouse is hover the bar. The next problem is the value are cropped on the top of the Chart
Here's my code :
function assignChart(ctx, dataArray) {
const dataLabel = ["Paris", "Milan", "London", "Florence", "New York", "Not specified"];
return (new Chart(ctx, {
type: 'bar',
data: {
labels: dataLabel,
datasets: [{
data: dataArray,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
events: [],
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
display: false,
beginAtZero:true,
}
}]
},
animation: {
duration : 1,
onComplete : function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(bar, index) {
if (dataset.data[index] > 0) {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y);
}
});
});
}
}
}
}));
}
Ps : i'm using ChartJS 2.7.3

For the problem of yours the data labels getting cropped on the top, you can add padding to the through the layout option like this:
layout: {
padding: {
left: 0,
right: 0,
top: 15,
bottom: 0
}
}
See fiddle -> https://jsfiddle.net/xys1tqfn/1/

Related

How to pass my array of objects into a graph with Chart.js

Hello I am trying to present my array of objects in a graph with Chart.js here is the code
let timers = {neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
var detection = new Chart(c, {
type: 'bar',
data: {
labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 2,
data: timers,
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
The problem is that the graph does not take as labels the one that I am giving to it but instead it takes as labels the names from the object array and due to that I cannot resize the x labels to be bigger. Thanks in advance for any tips.
As per the chart js documentation, when you give a map (key,value) to data field like timers in your case, chart js automatically takes keys as labels and values as data points to be plotted.
So, if you want to give your own labels in spite of this, you can add following snippet to your existing code.
var keys = Object.keys(timers);
var values = keys.map(function(v) { return timers[v]; });
and pass values instead of timers.
Full code -
let timers = {neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
var keys = Object.keys(timers);
var values = keys.map(function(v) { return timers[v]; });
var detection = new Chart(c, {
type: 'bar',
data: {
labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 2,
data: values,
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
Update:
As you want to update charts as timers are getting updated in setInterval, you have to put chart creation code also in setInterval function.
For example, you can refer to the following full html file
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js" integrity="sha512-Wt1bJGtlnMtGP0dqNFH1xlkLBNpEodaiQ8ZN5JLA5wpc1sUlk/O5uuOMNgvzddzkpvZ9GLyYNa8w2s7rqiTk5Q==" crossorigin="anonymous" referrerpolicy="no-referrer">
</script>
<script>
var i = 0;
setInterval(updateChart,3000);
function updateChart(){
var c = document.getElementById("myChart");
let chartStatus = Chart.getChart("myChart"); // <canvas> id
if (chartStatus != undefined) {
chartStatus.destroy();
}
i = i+1;
let timers;
if(i%2==0){
timers = {neutral: 20, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
}
else{
timers = {neutral: 0, happy: 20, sad: 0, angry: 0, surprised: 0, disgust: 0};
}
var keys = Object.keys(timers);
var values = keys.map(function(v) { return timers[v]; });
var detection = new Chart(c, {
type: 'bar',
data: {
labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 2,
data: keys.map(function(v) { return timers[v]; }),
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
}
</script>
</head>
<button onclick="updateChart()">Update Chart</button>
<canvas id="myChart" width="100" height="100"></canvas>
You can run this html code for better understanding.
You just need to let the labels array out of the chart like so:
const ctx = document.getElementById('chartJSContainer').getContext('2d');
const timers = {
neutral: 10,
happy: 0,
sad: 0,
angry: 0,
surprised: 0,
disgust: 20
};
const detection = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
fill: false,
backgroundColor: [
'rgba(255, 99, 132, 0.2)', // neutral
'rgba(54, 162, 235, 0.2)', // happy
'rgba(255, 206, 86, 0.2)', // sad
'rgba(75, 192, 192, 0.2)', // angry
'rgba(153, 102, 255, 0.2)', // surprised
'rgba(255, 159, 64, 0.2)' // disgust
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 2,
data: timers,
}]
},
options: {
indexAxis: 'x',
responsive: true,
plugins: {
legend: {
display: false,
labels: {
font: {
size: 50
}
}
},
title: {
display: true,
text: "Emotion timers"
}
}
}
});
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>

ChartJS Only Show Large Font Size for a Specific Tick

I am attempting to emphasize a specific value on the X-Axis if it meets a specific condition.
For example, in my codepen I want to only change the font size of the 'blue' bar. Is this even possible with Chart.js?
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}],
xAxes: [{
ticks: {
//only show large font size for 'Blue'
fontSize: 16
}
}]
}
}
});
Chartjs doesn't have a public api to do this but you can modify internal _ticks on beforeDraw and make the label "Blue" as major: true then that label will be drawn using the major styling in tick configuration options.
Also use this with caution since it relies on internal implementation and thus might break in future releases (very unlikely to happen but just saying).
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}],
xAxes: [{
ticks: {
fontSize: 16,
major: {
fontSize: 20
}
}
}]
}
},
plugins: [{
beforeDraw: function({ chart }, options) {
chart.boxes
.find(box => box.id === "x-axis-0")
._ticks
.find(tick => tick.label === "Blue")
.major = true;
}
}]
});
<canvas id="myChart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
PS: Just in case someone is wondering how I know this internal implementation I searched fillText in chartjs github source code and console.log(myChart) xD
Looks like it's not possible according to their docs. You can only do something like uppercase needed label with callback function
xAxes: [{
ticks: {
fontSize: 16,
callback: v => v === 'Blue' ? v.toUpperCase() : v
}
}]
For chartjs 3.0 and higher, it can be done by using scriptable-options. Include it like this into your options for ticks:
options: {
scales: {
x: {
ticks: {
font: {
size: (c) => {
if (c.index==1){
return 20 // at tick label with idx one set fontsize 20
}
else {
return 12 // for all other tick labels set fontsize 12
}
},
},
},
},
},
},

Chartjs - Add backgroundColor for labels radar chart

>>> Radar chart labels with background color
Hi there, I just want to ask for an option to add the background color (a rounded rect with bg color) for labels (individually) in Chartjs. Is there any callback that I can apply for changing this, any help is appreciated with best regards!
This is the current code:
let chart = new Chart('chart-0', {
type: 'radar',
data: radarChartData,
options: {
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Radar Chart | Chart.js',
fontSize: 16
},
scale: {
ticks: {
beginAtZero: true
},
pointLabels: {
fontSize: 14, // fontSize is ok
fontColor: presets.blue, // fontColor is accessible
backgroundColor: presets.yellow //This is not working for sure!
}
},
animation: {
animateScale: true,
animateRotate: true
}
}
});
You can do using backgroundColor.
data: {
labels: chart_label,
datasets: [{
label: '# of Votes',
data: chart_data,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
In case someone needs the answer, I did posted in in chartjs and Tim has done it so well: https://github.com/chartjs/Chart.js/issues/5085
Rgrds,

Pagination in Bar chart using ChartJS

I am using chartJS for display some data with Bar Chart. there are some issues with chartJs. When i have to much data-filed for example 100 or more data-field and it have long lasting label its looks like ugly.
how to config bar chart ?
here is my bar chart screenshot
here is my FIDDLE
in above example i have 100 data-filed, can i paginate this bar-chart ?
here is my code
var lbl = [];
var dt = [];
for(var i = 1;i<=100;i++){
lbl.push("this_is_my_lable_name_"+i);
}
for(var i = 1;i<=100;i++){
dt.push(Math.floor((Math.random() * 100) + 1));
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: lbl,
datasets: [{
label: '# of Votes',
data: dt,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
You can try this solution to consider the chart scroll like this:
Clone a different canvas for y axis so that when you scroll then only bars will appear to move
Adding the canvas for y axis
<canvas id="myChartAxis" height="600" width="0"></canvas>
Now cloning the axis
var sourceCanvas = myLiveChart.chart.canvas;
var copyWidth = myLiveChart.scales['y-axis-0'].width - 10;
var copyHeight = myLiveChart.scales['y-axis-0'].height + myLiveChart.scales['y-axis-0'].top + 10;
var targetCtx = document.getElementById("myChartAxis").getContext("2d");
targetCtx.canvas.width = copyWidth;
targetCtx.drawImage(sourceCanvas, 0, 0, copyWidth, copyHeight, 0, 0, copyWidth, copyHeight);
For a Demo see this FIDDLE
For better visualization its better to avoid labels in x axis and show this info intuitive via tool tip anyhow
You could wrap the canvas with a wrapper class and change its width accordingly which suites you the best. also, if you don't want the chart to cover entire screen, you can wrap it with another wrapper class.
var lbl = [];
var dt = [];
for (var i = 1; i <= 100; i++) {
lbl.push("this_is_my_lable_name_" + i);
}
for (var i = 1; i <= 100; i++) {
dt.push(Math.floor((Math.random() * 100) + 1));
}
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: lbl,
datasets: [{
label: '# of Votes',
data: dt,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
.wrapper {
width: 600px;
height: 400px;
overflow-x: scroll;
}
.chartWrapper {
width: 6000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="wrapper">
<div class="chartWrapper">
<canvas id="myChart" height="19"></canvas>
</div>
</div>
JSFiddle

Prevent size of canvas chart js to equal window height and width

I am using chartjs to display data and the chart (canvas) takes up 100% width and 100% height of the window.
I want to reduce this to be 600px by 600px. To do this I tried using
Chart.defaults.global.legend.fullWidth = false; however this didn't work.
I have created a jsfiddle here for your convenience.
See code below:
HTML
<canvas id="myChart" width="400" height="400"></canvas>
JS
var ctx = document.getElementById("myChart");
Chart.defaults.global.defaultFontColor = "#000";
Chart.defaults.global.legend.fullWidth = false;
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: labels,
datasets: [{
label: '# of Followers',
data: followers,
backgroundColor: [
'rgba(255, 99, 132, 0.9)',
'rgba(54, 162, 235, 0.9)',
'rgba(255, 206, 86, 0.9)',
'rgba(75, 192, 192, 0.9)',
'rgba(153, 102, 255, 0.9)',
'rgba(255, 159, 64, 0.9)'
],
borderColor: [
'rgba(255,99,132,1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 5
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
Add 'responsive: false' to the chart options
options: {
responsive: false,
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}

Categories