Is their a way to rotate the legend on the left side of a bar chart vertically (in chartjs)? I can't seem to find it in the documentation.
Current:
Wanted:
Code:
chartData is an array containing the char data where chartData["yas"] is equal to the "Samples" legend title
let myChart = new Chart(chart, {
type: 'bar',
data: {
labels: chartData['labels'],
datasets: [{
label: chartData["yas"],
data: chartData['values'],
backgroundColor: '#6FB98F'
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'left'
}
},
scales: {
y: {
ticks: {
beginAtZero:true,
minRotation : 0
}
}
}
}
});
This is not possible with the current implementation of the legend in chart.js. You have 2 options, you can use a html legend and rotate that 90 degree with css. Or you can take the legend plugin as a basis and write the functionality yourself to rotate it and either use it or make a pr and get it into the main lib.
Related
I have some time based data I want a graphical representation of, and was hoping to use Chartjs to plot this.
The data looks something like the following:
Time State
--------------
7am up
9am down
10.45am out
17.35 up
Also, each "state" will have its own color, so I would use this as a bar color when using a bar graph
up = red
down = yellow
out = green
The end result I am after is a simple one row bar like the following...
I thought I may be able to use a Chartjs horizontal stacked bar chart (https://www.chartjs.org/docs/latest/charts/bar.html#horizontal-bar-chart) to do this somehow, but I just can't work out how to get this working.
Some (not working) experimental code is as follows:
private createChart(): void {
if (this.chart !== undefined) {
return;
}
Chart.register(BarController, PointElement, Tooltip, Legend, TimeScale, LinearScale, CategoryScale, LinearScale, BarElement);
const options: ChartOptions = {
plugins: {
legend: {
display: false,
},
title: {
display: false,
},
},
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
stacked: true,
type: 'time',
display: true,
// position: 'bottom',
time: {
unit: 'minute',
displayFormats: {
minute: 'h:mm a'
}
}
},
x: {
stacked: false,
}
}
};
this.chart = new Chart(this.canvasRef.nativeElement, {
type: 'bar',
data: this.chartData,
options
});
this.chart.config.options.scales.y.min = new Date('2023-02-13T06:19:31.842Z').getTime();
const labels = [
'up',
'down'
// 'Dataset 2'
];
const d1 = new Date('2023-02-13T06:20:32.842Z').getTime();
const d2 = new Date('2023-02-13T06:21:33.842Z').getTime();
this.chartData = {
labels,
datasets: [{
label: 'up',
data: [{x: 10, y: d1}],
backgroundColor: 'red',
},
{
label: 'down',
data: [{x: 20, y: d2}],
backgroundColor: 'green',
}
]
};
this.chart.update();
}
In the above I have tried various combinations of labels, x values, y values, data shapes, but I only even get an empty graph.
Perhaps this is not really possible (I am trying to use the wrong component).
How can I achieve this using chartjs?
Update
Using example from #winner_joiner below, I have put a copy of it at plunkr and have tried to use the time in the x axis, but can see it is still not plotting the bars using the dates as the length
Well your code basically works, here a slightly modified version of your code.
After your comments and updated question, I reworke the example (seen below). Although it is possible to do with chart.js the question is, maybe for this specific task a different library or solution would be better/more convenient.
Update Chart, with some similar values from your question:
(I'm using here momentjs, since it is recommend usually needed form date/time actions in chartjs, as mentioned in the documentation)
const d0 = moment.duration('07:00:00').asMinutes();
const d1 = moment.duration('09:00:00').asMinutes();
const d2 = moment.duration('10:45:00').asMinutes();
const d3 = moment.duration('17:35:00').asMinutes();
const d4 = moment.duration('19:00:00').asMinutes();
let values = [d0, d1, d2, d3, d4];
let data = {
labels: [''],
datasets: [{
label: 'up',
axis: 'y',
data: [d1],
backgroundColor: 'red',
},{
label: 'down',
axis: 'y',
data: [d2],
backgroundColor: 'yellow',
},{
label: 'out',
axis: 'y',
data: [d3],
backgroundColor: 'green',
},{
label: 'up',
axis: 'y',
data: [d4],
backgroundColor: 'red',
}
]
};
const config = {
data,
type: 'bar',
options:{
plugins: {
tooltip: {
mode: 'dataset',
callbacks: {
label: function(item){
return moment().startOf('day').add({ minute: item.raw}).format('HH:mm');
}
}
},
legend: {
display: false,
},
title: {
display: false,
},
},
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
min: d0,
ticks: {
callback: function(value, index, ticks) {
return moment().startOf('day').add({ minute: value}).format('HH:mm');
}
},
afterBuildTicks: axis => axis.ticks = values.map(v => ({ value: v }))
},
y: {
stacked: true
},
}
}};
new Chart(document.getElementById("chart"), config);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<script src="//cdn.jsdelivr.net/npm/moment#^2"></script>
<script src="//cdn.jsdelivr.net/npm/chartjs-adapter-moment#^1"></script>
<div class="chart" style="height:184px; width:350px;">
<canvas id="chart" ></canvas>
</div>
I previously had a scatter graph in Chart.js 2 with the zoom plugin, in which I just had to add data and change the xAxis ticks' min/max to see a nice animated horizontal scroll from my old xAxis range to my new xAxis range.
For some reason I now use Chart.js 3.24 and the zoom plugin 1.1.1. Now the same graph with nearly the same options became quite ugly when animated:
newly added points e.g. at position (X,Y) have an animation going from (X,0) to (X,Y), instead of appearing directly at (X,Y).
when a point from a dataset is at the same position than a line from another dataset, they move at a different speed.
if many points and line are added, sometimes the lines are only shown after the "scrolling animation" ended.
sometimes a point appear at its correct final position before the "scrolling animation" even started.
The only solution I found was to disable animation when updating my graph, then use window.requestAnimationFrame to manually pan the graph myself with the zoom plugin.
Are you aware of a better/simpler recommended way to achieve this ?
Thanks in advance,
My old Chart.js options:
let zoom_options = {
pan: {
enabled: true,
mode: 'x',
rangeMin: { x: 0, y: null},
rangeMax: { x: null, y: null}
},
zoom: {
enabled: true,
drag: false,
mode: 'x',
rangeMin: { x: 0, y: null },
rangeMax: { x: null, y: null },
speed: 0.1
}
};
var ctx = graph.getContext('2d');
this._chartjs = new Chart(ctx, {
type: 'scatter',
data: {
datasets: []
},
options: {
legend: {
//display: false
},
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
}]
},
plugins: {
zoom: zoom_options // https://github.com/chartjs/chartjs-plugin-zoom
}
}
});
My old line options :
{
label: name,
showLine: false,
fill:false,
spanGaps: false, // I have some NaN values in my datasets.
backgroundColor: color.points_borders,
borderColor: color.line,
borderWidth:5,
pointRadius:5,
pointBorderWidth:2,
pointBorderColor: color.points_borders,
pointBackgroundColor: color.points,
data: []
}
My old update function:
this._chartjs.options.scales.xAxes[0].ticks.min = min;
this._chartjs.options.scales.xAxes[0].ticks.max = length;
this._chartjs.update();
I made a horizontal bar chart using Chart.js. In default setting all the legends are shown all together like this
there is no gap among them. I want to show each legend aligned with each bar like this
I tried so many solutions but none of them worked. Is it possible to show legends right and center aligned with each bar in chart.js?
I am using Chart.js (v.3.7)
The behavior you are looking for can possibly be achieved by using the padding option in the Legend Label Configuration and trying to find the correct value.
This could look something like this:
const chart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
plugins: {
legend: {
display: true,
labels: {
padding: 15 // change according to testing
}
}
}
}
});
You would usually not use a legend for this but instead label the axis directly as described in the link below.
Have a look at the documentation: https://www.chartjs.org/docs/latest/axes/cartesian/#tick-configuration
It provides an example on how to use axis labels like that:
// config
const config = {
type: 'bar',
data,
options: {
indexAxis: 'y',
scales: {
y: {
ticks: {
crossAlign: 'far',
}
}
}
}
};
// setup
const labels = ["Label 1", "Label 2", "Label 3"]
const data = {
labels: labels,
datasets: [{
label: 'My dataset',
borderWidth: 1,
data: [65, 59, 80],
}]
};
I'd like to conditionally add a strikethrough to tick labels. As far as I can tell, there's no option to natively do that through Chart.js. Is there a way to hook in through the axes callbacks to add that?
I don't know if that is possible because you are dealing with a canvas element, but you can customize the text in the labels by using the ticks callback as in this example:
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: ["One", "Two", "Three", "Four", "Five"],
datasets: [
{
label: "A chart",
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850"],
data: [2478, 5267, 734, 784, 433]
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'A chart with columns and custom vertical labels'
},
scales: {
yAxes: [{
ticks: {
callback: function (value, index, values) {
return index % 2 == 0 ? value : '**' + value + '**';
}
}
}]
}
}
});
Note the callback funcion there, maybe you can use this to give some labels a distinctive text.
The chart of this example looks like this:
I would like to update specific column background colour but I couldn't do this. Seem like it is very easy but all the solution I tried out from google doesn't work. The code is as below.
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels : ["A","B","C","D","E"],
datasets: [{
data : [<?php echo $graph_data;?>],
backgroundColor: "rgba(0,0,220,0.5)",
borderColor: "rgba(0,0,220,1)",
borderWidth: 2
}]
}
});
//I would like to achieve something like this, let's say change the first and second bar's background color
myChart.datasets[0].bars[0].fillColor = "rgba(220,0,0,0.5)";
myChart.datasets[0].bars[1].fillColor = "rgba(220,0,0,0.5)";
myChart.update();
I had an old code which run succesfully under version 1.0.1-beta.4, but now I world like to use the latest version 2.5.0, and then I faced this issue.
Thanks for any helps!
You can just pass an array to the backgroundColor bar chart dataset property (instead of a single color) where the position in the array maps to the position in the data array.
For example, if you have 3 bars and want all 3 to be a different color, just pass an array to backgroundColor where all 3 elements have a different color value.
var ctx = document.getElementById("canvas").getContext("2d");
var myBar = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Car", "Bike", "Walking"],
datasets: [{
label: 'Fuel',
backgroundColor: [
chartColors.red,
chartColors.blue,
chartColors.yellow],
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
]
}]
},
options: {
title: {
display: true,
text: "Chart.js - Different Bar Colors"
},
tooltips: {
mode: 'index',
intersect: false
},
legend: {
display: false,
},
responsive: true,
}
});
Here is a codepen example demonstrating this.