Related
I am trying to create a stacked horizontal bar chart with an average line on each bar using the ChartJS library. I tried several times and searched on the Internet but I did not find out any satisfying answers. I appreciate your helping. Thanks.
Example:
.
In this example, the red line on each bar implies the average value of its group.
To create the stacked horizontal bar chart, please see
https://jsfiddle.net/lamtn862004/9wm1krqf/10/.
var data = {
labels: ["January", "February", "March"],
datasets: [
{
label: "Dogs",
backgroundColor: "rgba(237, 192, 169)",
data: [20, 10, 25],
stack: 1,
xAxisID: 'x-axis-0',
yAxisID: 'y-axis-0'
},
{
label: "Cats",
backgroundColor: "rgba(253, 234, 175)",
data: [70, 85, 65],
stack: 1,
xAxisID: 'x-axis-0',
yAxisID: 'y-axis-0'
},
{
label: "Birds",
backgroundColor: "rgba(179, 211, 200)",
data: [10, 5, 10],
stack: 1,
xAxisID: 'x-axis-0',
yAxisID: 'y-axis-0'
},
]
};
var ctx = document.getElementById("myChart").getContext("2d");
new Chart(ctx, {
type: 'groupableHBar',
data: data,
options: {
scales: {
yAxes: [{
stacked: true,
type: 'category',
id: 'y-axis-0'
}],
xAxes: [{
stacked: true,
type: 'linear',
ticks: {
beginAtZero:true
},
gridLines: {
display: false,
drawTicks: true,
},
id: 'x-axis-0'
},
{
stacked: true,
position: 'top',
type: 'linear',
ticks: {
beginAtZero:true
},
id: 'x-axis-1',
gridLines: {
display: true,
drawTicks: true,
},
display: false
}]
}
}
});
Now, I want to add the average line to each bar (as shown in the image).
Also, do you know the other solutions with open-source libraries for doing this?
The lines can be drawn using floating bars tied to the separate axis y2. To do so, you need to add another dataset as follows (I don't exactly understand what values you want to display, hence I randomly chose 40, 65 and 55):
{
label: "Lines",
backgroundColor: "rgb(255, 0, 0)",
data: [40, 65, 55].map(v => [v - 0.3, v + 0.3]),
yAxisID: 'y2',
order: -1
}
Further you must define a new scales option as shown below:
y2: {
display: false
}
Please take a look at your amended runnable code and see how it works.
var data = {
labels: ["January", "February", "March"],
datasets: [{
label: "Dogs",
backgroundColor: "rgba(237, 192, 169)",
data: [20, 10, 25]
},
{
label: "Cats",
backgroundColor: "rgba(253, 234, 175)",
data: [70, 85, 65]
},
{
label: "Birds",
backgroundColor: "rgba(179, 211, 200)",
data: [10, 5, 10]
},
{
label: "Lines",
backgroundColor: "rgb(255, 0, 0)",
data: [40, 65, 55].map(v => [v - 0.3, v + 0.3]),
yAxisID: 'y2',
order: -1
}
]
};
new Chart('myChart', {
type: 'bar',
data: data,
options: {
indexAxis: 'y',
plugins: {
legend: {
display: false
}
},
scales: {
y: {
stacked: true,
grid: {
display: false
}
},
y2: {
display: false
},
x: {
stacked: true,
beginAtZero: true,
grid: {
display: false
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>
I'm working on a project that could display sensing data on local web pages in real time with Django and I made this stream live data chart. But I don't need to this realtime x-axis ticks. I want to make the x-axis starting at zero and increasing 1 step by one second.
I think "xAxes type realtime" is the key, but I'm new to this and it's hard for me to solve alone, so I need your help.
enter image description here
<script>
var chartColors = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)'
};
function onRefresh(chart) {
var now = Date.now();
chart.data.datasets.forEach(function(dataset) {
dataset.data.push({
x: now,
y: GetData()
});
});
}
var color = Chart.helpers.color;
var config = {
type: 'line',
data: {
datasets: [{
backgroundColor: [
'rgba(100, 200, 200, 0)'
],
borderColor: chartColors.blue,
fill: false,
lineTension: 0,
borderDash: [8, 0],
data: [],
borderWidth:3,
pointRadius:0,
}]
},
options: {
legend:{
display:false
},
title: {
display: true,
text: 'Some Chart',
fontSize:20,
fontFamily:"Tahoma"
},
scales: {
xAxes: [{
ticks:{
beginAtZero: true
},
gridLines:{
display:true
},
type: 'realtime',
display:true,
position:'bottom',
realtime: {
duration: 20000,
refresh: 1000,
delay: 0,
onRefresh: onRefresh
}
}],
yAxes: [{
gridLines:{
display:true
},
scaleLabel: {
display: true,
labelString: 'value'
}
}]
},
}
};
window.onload = function() {
var ctx = document.getElementById('myChart').getContext('2d');
window.myChart = new Chart(ctx, config);
};
</script>
Is there any other way to make streaming live graph with Django, please let me know.
I solved this myself. The key was about 'xAxes ticks callback'. thank you.
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 am trying to build a graph similar to the one in the image
but I can't find the right way to do it, I want to join the line with the bar on the same axis, and for every bar I want to define the starting Y position and the ending Y position, I tried to do it using multi axis but it didn't work, what I tried is something similar to this
const data = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', July'],
datasets: [{
label: 'Sales',
type:'line',
data: [51, 65, 40, 49, 60, 37, 40],
fill: false,
borderColor: '#EC932F',
backgroundColor: '#EC932F',
pointBorderColor: '#EC932F',
pointBackgroundColor: '#EC932F',
pointHoverBackgroundColor: '#EC932F',
pointHoverBorderColor: '#EC932F',
yAxisID: 'y-axis-2'
},{
type: 'bar',
label: 'Visitor',
data: [200, 185, 590, 621, 250, 400, 95],
fill: false,
backgroundColor: '#71B37C',
borderColor: '#71B37C',
hoverBackgroundColor: '#71B37C',
hoverBorderColor: '#71B37C',
yAxisID: 'y-axis-1'
}]
};
const options = {
responsive: true,
tooltips: {
mode: 'label'
},
elements: {
line: {
fill: false
}
},
scales: {
xAxes: [
{
display: true,
gridLines: {
display: false
},
labels: {
show: true
}
}
],
yAxes: [
{
type: 'linear',
display: true,
position: 'left',
id: 'y-axis-1',
gridLines: {
display: false
},
labels: {
show: true
}
},
{
type: 'linear',
display: true,
position: 'right',
id: 'y-axis-2',
gridLines: {
display: false
},
labels: {
show: true
}
}
]
}
};
but this way, there will be two axes, one on the left and the other on the right side, but both start from the same position
I use Chart.js to create the horizontal bar of my chart. At this point I have is what is the first image.
But I need to create a "BackgroundBar" with percentage, but I do not know how I can do it. Can someone help me?
This is my output right Now.
This is the chart I want..
My code snippet is like below..
var bar_ctx = document.getElementById('bar-chart').getContext('2d');
var purple_orange_gradient = bar_ctx.createLinearGradient(0, 0, 250, 0);
purple_orange_gradient.addColorStop(0.0, 'rgb(237, 28, 36)');
purple_orange_gradient.addColorStop(0.25, 'rgb(228, 81, 173)');
purple_orange_gradient.addColorStop(0.5, 'rgb(194, 112, 215)');
purple_orange_gradient.addColorStop(0.75, 'rgb(158, 143, 239)');
purple_orange_gradient.addColorStop(1.0, 'rgb(106, 159, 247)');
var bar_chart = new Chart(bar_ctx, {
type: 'horizontalBar',
data: {
labels: ["Red", "Blue"],
datasets: [{
label: '# of Votes',
data: [12, 19],
backgroundColor: purple_orange_gradient,
hoverBackgroundColor: purple_orange_gradient,
borderWidth: 0
}]
},
options: {
scales: {
yAxes: [{
categorySpacing: 0,
barThickness: 20
}],
xAxes: [{
ticks: {
beginAtZero: true
//max:100
}
}]
}
}
});
<canvas id="bar-chart" width="300" height="125"></canvas>
This can be achieved using a ChartJS plugin called - chartjs-plugin-annotation.
DEMO
var bar_ctx = document.getElementById('bar-chart').getContext('2d');
var purple_orange_gradient = bar_ctx.createLinearGradient(0, 0, 250, 0);
purple_orange_gradient.addColorStop(0.0, 'rgb(237, 28, 36)');
purple_orange_gradient.addColorStop(0.25, 'rgb(228, 81, 173)');
purple_orange_gradient.addColorStop(0.5, 'rgb(194, 112, 215)');
purple_orange_gradient.addColorStop(0.75, 'rgb(158, 143, 239)');
purple_orange_gradient.addColorStop(1.0, 'rgb(106, 159, 247)');
var bar_chart = new Chart(bar_ctx, {
type: 'horizontalBar',
data: {
labels: ["Red", "Blue"],
datasets: [{
label: '# of Votes',
data: [12, 19],
backgroundColor: purple_orange_gradient,
hoverBackgroundColor: purple_orange_gradient,
borderWidth: 0
}]
},
options: {
scales: {
yAxes: [{
categorySpacing: 0,
barThickness: 20
}],
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
annotation: {
annotations: [{
type: 'box',
drawTime: 'beforeDatasetsDraw',
id: 'bg-bar-1',
xScaleID: 'x-axis-0',
xMin: 0,
xMax: 10,
backgroundColor: '#7f7f7f',
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script src="https://cdn.rawgit.com/chartjs/chartjs-plugin-annotation/master/chartjs-plugin-annotation.min.js"></script>
<canvas id="bar-chart" width="300" height="125"></canvas>
To learn more about this plugin and it's use cases, refer here.