I have the below stacked group chart.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<script>
var barChartData = {
labels: ['January', 'March', 'June', 'September', 'December'],
datasets: [{
label: 'Apple',
borderColor: 'rgba(255, 50, 50,1)',
backgroundColor: 'rgba(255, 50, 50,0.5)',
stack: 'Stack 0',
data: [3,6,4,8,2]
}, {
label: 'Orange',
borderColor: 'rgba(255, 160, 242,1)',
backgroundColor: 'rgba(255, 160, 242,0.5)',
stack: 'Stack 0',
data: [2,1,3,0,1]
}, {
label: 'Pear',
borderColor: 'rgba(79, 158, 255,1)',
backgroundColor: 'rgba(79, 158, 255,0.5)',
stack: 'Stack 0',
data: [3,4,1,5,2]
}, {
label: 'Apple',
borderColor: 'rgba(255, 50, 50,1)',
backgroundColor: 'rgba(255, 50, 50,0.5)',
stack: 'Stack 1',
data: [7,16,10,8,5]
},{
label: 'Mango',
borderColor: 'rgba(100, 244, 97,1)',
backgroundColor: 'rgba(100, 244, 97,0.5)',
stack: 'Stack 1',
data: [4,9,12,5,7]
}, {
label: 'Banana',
borderColor: 'rgba(255, 252, 91,1)',
backgroundColor: 'rgba(255, 252, 91,0.5)',
stack: 'Stack 1',
data: [3,6,13,14,5]
}, {
label: 'Orange',
borderColor: 'rgba(255, 160, 242,1)',
backgroundColor: 'rgba(255, 160, 242,0.5)',
stack: 'Stack 1',
data: [7,12,3,0,2]
}, {
label: 'Cherry',
borderColor: 'rgba(255, 132, 38,1)',
backgroundColor: 'rgba(255, 132, 38,0.5)',
stack: 'Stack 1',
data: [8,4,7,11,6]
}, {
label: 'Pear',
borderColor: 'rgba(79, 158, 255,1)',
backgroundColor: 'rgba(79, 158, 255,0.5)',
stack: 'Stack 1',
data: [8,14,9,12,16]
}]
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: barChartData,
options: {
legend: {
display:true,
},
tooltips: {
mode: 'x',
intersect: false
},
responsive: true,
scales: {
xAxes: [{
stacked: true,
}],
yAxes: [{
stacked: true
}]
}
}
});
</script>
I would like to do two things:
1) Remove the redundant Apple, Orange and Pear labels
2) Highlight/Darken just the border on the individual stacks in the graph with the colors of those individual stacks. Like how the legend is.
Any help would be greatly appreciated.
Image of my graph
You can add custom logic to legend options like:
options: {
legend: {
display: true,
labels: {
generateLabels: function (chart) { ...
You can reach the labels here, customize their color, text, you can group them etc. So in this case you have to group the labels by their text first like
const labelTexts = []
const newLabels = []
labels = Chart.defaults.global.legend.labels.generateLabels(chart);
// group labels
labels.map((label) => {
if (labelTexts.indexOf(label.text) === -1) {
labelTexts.push(label.text)
}
})
labelTexts.map((text) => {
labels.map((label) => {
if (label.text === text) {
newLabels.push(label)
}
})
})
Then you can remove the redundant labels like:
for (var i = 0; i < newLabels.length - 2; i++) {
if (newLabels[i].text !== newLabels[i + 1].text) {
newLabels2.push(newLabels[i])
}
}
Check a working example here
Related
hi i have a question on adding title to axes for line chart. i am current using react-chartjs-2 and chart.js v4.2 . i have a line chart with 3 different datasets and i want two y axes. this is my current config for line component
const optionsMulti = {
responsive: true,
interaction: {
mode: "index" as const,
intersect: false,
},
stacked: false,
plugins: {
title: {
display: true,
text: "Test Chart",
},
},
scales: {
y: {
type: "linear" as const,
display: true,
position: "left" as const,
title: { display: true, title: "title1" },
},
y1: {
type: "linear" as const,
display: true,
position: "right" as const,
grid: {
drawOnChartArea: false,
},
title: { display: true, text: "title2" },
},
},
};
const data = {
labels: "label",
datasets: [
{
label: "one",
data: data1,
borderColor: "rgb(255, 99, 132)",
backgroundColor: "rgba(255, 99, 132, 0.5)",
yAxisID: "y",
},
{
label: "two",
data: data2,
borderColor: "rgb(53, 162, 235)",
backgroundColor: "rgba(53, 162, 235, 0.5)",
yAxisID: "y",
},
{
label: "three",
data: data3,
borderColor: "rgba(75, 192, 192)",
backgroundColor: "rgba(75, 192, 192, 0.5)",
yAxisID: "y1",
},
],
}
<Line options={optionsMulti} data={data} />
title for yAxisID: "y1", is showing but yAxisID: "y" title is not showing.
screenshot of current chart
how can i set the config for both y axes to show titles?
Working with chart js and trying to display some annotations but I am having some bad luck and nothing is showing. Any idea?
This is my config:
const config = {
type: 'line',
data: data,
options: {
responsive: true,
plugins: {
autocolors: false,
legend: {
position: 'top',
},
annotation: {
annotations: [{
point1: {
type: 'point',
xValue: 500,
yValue: 600,
backgroundColor: 'rgba(255, 99, 132, 0.25)'
},
line1: {
type: 'line',
yMin: 60,
yMax: 60,
borderColor: 'rgb(255, 99, 132)',
borderWidth: 2,
}
}]
},
title: {
display: true,
text: 'Beta Revenue'
}
}
},
};
I want to create stacked bar chart with groups in use chart.js v3. I
my chart output
I did it and i am getting the following image. But here, instead of the sum of label 1 and label2 appearing as 7000, how can I show the intersection of label 1 and label 2 together as 4000 by starting from the x-axis.
type: 'bar',
data: {
labels: labelsVals,
datasets: [
{
label: 'Label 1',
data: seriesValsPaid,
backgroundColor: 'rgba(21, 169, 225, 0.6)',
borderColor: 'rgba(21, 169, 225, 1)',
borderWidth: 1,
stack: 'first',
},
{
label: 'Label 2',
data: seriesValsWaiting,
backgroundColor: 'rgba(21, 122, 225, 0.6)',
borderColor: 'rgba(21, 122, 225, 1)',
borderWidth: 1,
stack: 'first',
},
{
label: 'Label 3',
data: seriesValsOutgoing,
backgroundColor: 'rgba(255, 0, 0, 0.6)',
borderColor: 'rgba(255, 0, 0, 1)',
borderWidth: 1,
stack: 'second',
}
]
},
});
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
'bar-x-axis1': {
stacked: true,
display:false
},
'bar-x-axis2': {
stacked: true,
display:false
},
y: {
stacked: false,
beginAtZero: true
// display:false
}
}
}
This is how I solved the problem.
I have the below ChartJS code and I would like to hide the grid vertical lines only and not the horizontal ones and keep only one vertical line per two like in the capture below:
image]1
Thanks.
<canvas id="line-chart" width="800" height="450"></canvas>
new Chart(document.getElementById("line-chart"), {
type: 'line',
data: {
labels: [1500,1600,1700,1750,1800,1850,1900,1950,1999,2050],
datasets: [{
data: [86,114,106,106,107,111,133,221,783,2478],
label: "Africa",
borderColor: "#3e95cd",
fill: false
}, {
data: [282,350,411,502,635,809,947,1402,3700,5267],
label: "Asia",
borderColor: "#8e5ea2",
fill: false
}, {
data: [168,170,178,190,203,276,408,547,675,734],
label: "Europe",
borderColor: "#3cba9f",
fill: false
}, {
data: [40,20,10,16,24,38,74,167,508,784],
label: "Latin America",
borderColor: "#e8c3b9",
fill: false
}, {
data: [6,3,2,2,7,26,82,172,312,433],
label: "North America",
borderColor: "#c45850",
fill: false
}
]
},
options: {
title: {
display: true,
text: 'World population per region (in millions)'
}
}
});
Just add grid color as function in options for x axis scale and conditionally change the colors like its done below:
var chartInstance = new Chart(document.getElementById("chartJSContainer"), {
type: 'line',
data: {
labels: [1500, 1600, 1700, 1750, 1800, 1850, 1900, 1950, 1999, 2050],
datasets: [{
data: [86, 114, 106, 106, 107, 111, 133, 221, 783, 2478],
label: "Africa",
borderColor: "#3e95cd",
fill: false
}, {
data: [282, 350, 411, 502, 635, 809, 947, 1402, 3700, 5267],
label: "Asia",
borderColor: "#8e5ea2",
fill: false
}, {
data: [168, 170, 178, 190, 203, 276, 408, 547, 675, 734],
label: "Europe",
borderColor: "#3cba9f",
fill: false
}, {
data: [40, 20, 10, 16, 24, 38, 74, 167, 508, 784],
label: "Latin America",
borderColor: "#e8c3b9",
fill: false
}, {
data: [6, 3, 2, 2, 7, 26, 82, 172, 312, 433],
label: "North America",
borderColor: "#c45850",
fill: false
}]
},
options: {
title: {
display: true,
text: 'World population per region (in millions)'
},
scales: {
x: {
grid: {
display: true, //Make it false to remove all the vertical lines.
color: function(context) {
if (context.tick.value %2 == 0) {
return 'gray';
} else {
return 'white';
}
},
}
}
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.3.1/dist/chart.js"></script>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
I don’t really use chart.js so there may be a better way to do this. I think there may be a built in way to use a callback for this but I couldn’t figure it out. Here’s what does work.
Add this function at the top to create an array of alternating colors.
let colors = [];
function gridColors() {
for (let i=0; i<10; i++) {
colors.push("rgba(0,0,0,0)")
colors.push("rgba(0,0,0,0.1)")
}
}
gridColors()
And in your options add the following
options: {
title: {
display: true,
text: 'World population per region (in millions)'
},
scales: {
x: {
grid: {
beginAtZero: true,
color: colors,
}
}
}
}
});
I have a strange issue. I'm getting the date from the database. All visualization was good. Then I deleted one record and add another one on the same date and time. But that record moved on the right in the chart instead to be ordered on left:
The js code is this:
$(document).ready(function(){
$.ajax({
url: "js/json/otv_fil_iskar/data.php",
method: "POST",
success: function(data) {
console.log(data);
var progress = document.getElementById('animationProgress');
var dateANDtime = [];
var Gblok9osx = [];
var Gblok9osy = [];
var Gblok11osx = [];
var Gblok11osy = [];
var Gfilblok10 = [];
var Gfilblok11 = [];
var Gcvn = [];
var Gndk2 = [];
for(var i in data) {
dateANDtime.push(data[i].to_char);
Gblok9osx.push(data[i].blok9osx);
Gblok9osy.push(data[i].blok9osy);
Gblok11osx.push(data[i].blok11osx);
Gblok11osy.push(data[i].blok11osy);
Gfilblok10.push(data[i].filblok10);
Gfilblok11.push(data[i].filblok11);
Gcvn.push(data[i].cvn);
Gndk2.push(data[i].ndk2);
}
var chartdata = {
labels: dateANDtime,
datasets : [
{fill: false,
label: 'Отвес блок 9 x',
backgroundColor: 'rgba(199, 228, 238, 0.75)',
borderColor: 'rgba(1, 150, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 0.75)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok9osx,
hidden: true
},
{fill: false,
label: 'Отвес блок 9 y',
backgroundColor: 'rgba(163, 147, 222, 0.75)',
borderColor: 'rgba(50, 10, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok9osy,
hidden: true
},
{fill: false,
label: 'Отвес блок 11 x',
backgroundColor: 'rgba(221, 221, 241, 0.75)',
borderColor: 'rgba(100, 100, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok11osx,
hidden: true
},
{fill: false,
label: 'Отвес блок 11 y',
backgroundColor: 'rgba(147, 227, 227, 0.75)',
borderColor: 'rgba(1, 200, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gblok11osy,
hidden: true
},
{fill: false,
label: 'Филтрация блок 10',
backgroundColor: 'rgba(139, 105, 132, 0.75)',
borderColor: 'rgba(255, 1, 200, 0.75)',
//hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(200, 200, 200, 1)',
data: Gfilblok10,
hidden: true
},
{fill: false,
label: 'Филтрация блок 11',
backgroundColor: 'rgba(0, 200, 1, 1)',
borderColor: 'rgba(0, 101,1, 0.75)',
hoverBackgroundColor: 'rgba(200, 200, 200, 1)',
hoverBorderColor: 'rgba(50, 50, 50, 1)',
data: Gfilblok11,
hidden: true
},
{fill: false,
label: 'КВН',
backgroundColor: 'rgba(30, 100, 100, 1)',
borderColor: 'rgba(100, 200,1, 0.75)',
hoverBackgroundColor: 'rgba(101, 200, 200, 1)',
hoverBorderColor: 'rgba(50, 50, 50, 1)',
data: Gcvn,
hidden: false
},
{fill: false,
label: 'Ниво дренажен кладенец',
backgroundColor: 'rgba(30, 100, 100, 1)',
borderColor: 'rgba(100, 200,1, 0.75)',
hoverBackgroundColor: 'rgba(101, 200, 200, 1)',
hoverBorderColor: 'rgba(50, 50, 50, 1)',
data: Gndk2,
hidden: true
}
]
};
$('#reset_zoom').click(function() {
barGraph.resetZoom();
})
$("#save-btn").click(function() {
$("#mycanvas").get(0).toBlob(function(blob) {
saveAs(blob, "chart_1.png");
});
});
var ctx = document.getElementById("mycanvas");
var barGraph = new Chart(ctx, {
type: 'line',
data: chartdata,
options: {
title: {
display: true,
text: 'Диаграма - Отвеси и филтрации'
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: '[mm] , [l/s]'
},
ticks: {
beginAtZero:false
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Дата/Час'
},
ticks: {
beginAtZero:true
}
}]
},
// Container for pan options
pan: {
// Boolean to enable panning
enabled: true,
// Panning directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow panning in the y direction
mode: 'y'
},
// Container for zoom options
zoom: {
// Boolean to enable zooming
enabled: true,
// Zooming directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow zooming in the y direction
mode: 'xy'
},
animation: {
duration: 2000,
onProgress: function(animation) {
progress.value = animation.currentStep / animation.numSteps;
},
onComplete: function() {
window.setTimeout(function() {
progress.value = 0;
}, 2000);
}
},
legend: {
display: true,
labels: {
//fontColor: 'rgb(255, 99, 132)'
usePointStyle: true
}
}
},
plugins: [{
beforeDraw: function(c) {
var reset_zoom = document.getElementById("reset_zoom"); //reset button
var ticks = c.scales['x-axis-0', 'y-axis-0'].ticks.length; //x-axis ticks array
var labels = c.data.labels.length; //labels array
if (ticks < labels) reset_zoom.hidden = false;
else reset_zoom.hidden = true;
}
}]
}); //end data
},
error: function(data) {
console.log(data);
}
});
});
The same think is happening when i don't have records in particular time of the day.
I changed xAxes option in the same graph and it's similar output:
xAxes: [{
type: 'time',
time: {
displayFormats: {
'hour': 'DD MMM YYYY г. HH:MM:SS ч.'
}
},
scaleLabel: {
display: true,
labelString: 'Дата/Час'
},
ticks: {
beginAtZero: true
}
}]
The order in the dataset is important because chart.js does not do any sorting of the values. Make sure that you fetch data from the database ordered by date and not id which usually is default.