I am trying to create a mixed stacked horizontal bar chart and line chart in Charts.js 3.2.0.
Expected behaviour: one axis at the bottom for the stacked bars including axes title and one axis at the top for the line chart.
Actual behaviour: all axes on the bottom with an additional extra axis displayed that doesn't seem to correspond with any dataset. No axes titles displayed.
Notes: the code has zero values for a few bars, these can be non-zero depending on data that is generated.
My code:
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
data: {
labels: ["Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6", ],
datasets: [{
type: "line",
label: "Earnings",
xAxisID: "A1",
data: [10000, 20000, 30000, 5000]
},
{
label: "CAT 1",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(255,59,59, 0.2)"],
borderColor: ["rgba(255,59,59, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 2",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(241,85,54, 0.2)"],
borderColor: ["rgba(241,85,54, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 3",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(235,106,55, 0.2)"],
borderColor: ["rgba(235,106,55, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 4",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(227,131,53, 0.2)"],
borderColor: ["rgba(227,131,53, 1)"],
borderWidth: 1,
data: [0, 0, 32.012777777778, 0, 0, 29.378611111111, ]
},
{
label: "CAT 5",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(221,171,54, 0.2)"],
borderColor: ["rgba(221,171,54, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 6",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(218,199,52, 0.2)"],
borderColor: ["rgba(218,199,52, 1)"],
borderWidth: 1,
data: [0, 44.195555555556, 0, 0, 38.79, 0, ]
},
{
label: "CAT 7",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(192,224,66, 0.2)"],
borderColor: ["rgba(192,224,66, 1)"],
borderWidth: 1,
data: [0, 0, 0, 14.921666666667, 0, 0, ]
},
{
label: "CAT 8",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(124,236,93, 0.2)"],
borderColor: ["rgba(124,236,93, 1)"],
borderWidth: 1,
data: [40.216666666667, 0, 0, 0, 0, 0, ]
},
]
},
options: {
responsive: true,
maintainAspectRatio: false,
indexAxis: "y",
scales: {
x: [
{
display: true,
position: "top",
type: "linear",
title: {
text: "cost",
display: true,
},
beginAtZero: true,
id: "A1",
},
{
id: "B1",
position: "bottom",
title: {
text: "hours",
display: false,
},
beginAtZero: true
}
],
y: {
display: true,
stacked: true,
//beginAtZero: true
}
}
}
});
</script>
jsfiddle
Screenshot of current behaviour
The x and y axis are no arrays anymore in v3, all scales are an object and you define the place with the position argument, also you dont specify the id in the object but the object key is the id
Example:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.0/chart.js"></script>
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
data: {
labels: ["Person 1", "Person 2", "Person 3", "Person 4", "Person 5", "Person 6", ],
datasets: [{
type: "line",
label: "Earnings",
xAxisID: "A1",
data: [10000, 20000, 30000, 5000]
},
{
label: "CAT 1",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(255,59,59, 0.2)"],
borderColor: ["rgba(255,59,59, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 2",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(241,85,54, 0.2)"],
borderColor: ["rgba(241,85,54, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 3",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(235,106,55, 0.2)"],
borderColor: ["rgba(235,106,55, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 4",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(227,131,53, 0.2)"],
borderColor: ["rgba(227,131,53, 1)"],
borderWidth: 1,
data: [0, 0, 32.012777777778, 0, 0, 29.378611111111, ]
},
{
label: "CAT 5",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(221,171,54, 0.2)"],
borderColor: ["rgba(221,171,54, 1)"],
borderWidth: 1,
data: [0, 0, 0, 0, 0, 0, ]
},
{
label: "CAT 6",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(218,199,52, 0.2)"],
borderColor: ["rgba(218,199,52, 1)"],
borderWidth: 1,
data: [0, 44.195555555556, 0, 0, 38.79, 0, ]
},
{
label: "CAT 7",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(192,224,66, 0.2)"],
borderColor: ["rgba(192,224,66, 1)"],
borderWidth: 1,
data: [0, 0, 0, 14.921666666667, 0, 0, ]
},
{
label: "CAT 8",
xAxisID: "B1",
type: "bar",
backgroundColor: ["rgba(124,236,93, 0.2)"],
borderColor: ["rgba(124,236,93, 1)"],
borderWidth: 1,
data: [40.216666666667, 0, 0, 0, 0, 0, ]
},
]
},
options: {
responsive: true,
maintainAspectRatio: false,
indexAxis: "y",
scales: {
A1:
{
display: true,
position: "top",
type: "linear",
title: {
text: "cost",
display: true,
},
beginAtZero: true,
id: "A1",
},
B1: {
id: "B1",
position: "bottom",
title: {
text: "hours",
display: false,
},
beginAtZero: true
},
y: {
display: true,
stacked: true,
}
}
}
});
</script>
fiddle: https://jsfiddle.net/Leelenaleee/7agx5hkr/1/
Related
i have a code which should give me an overlapping bar chart , one inside other in canvas js , something like below
Output Needed
So it should be combination of stacked horizontal graph , and one overlapping graph inside the first ( as in pic)
but am getting everything inside one main graph
below is the code .
var chart = new CanvasJS.Chart("chartContainer", {
theme: "light2",
title: {
text: "Chart Title"
},
reversed:true,
data: [
{
type: "error",
whiskerThickness: 0,
color: "#004ca0",
dataPoints: [
{ label: "Alpha", y: [0 , 71] },
]
},
{
type: "column",
axisXType: "secondary",
color: "#34dc00",
dataPoints: [
{ label: "Alpha", y: 60 },
]
},
{
type: "column",
axisXType: "secondary",
color: "#3cfa00",
dataPoints: [
{ label: "Alpha", y: 50 },
]
},
]
});
chart.render();
chart.data[0].set("stemThickness", chart.get("dataPointWidth") * 4 + 10);
<div id="chartContainer" style="height: 360px; width: 100%;"></div>
Thanks
var chart = new CanvasJS.Chart("chartContainer", {
theme: "light2",
title: {
text: "Chart Title"
},
reversed:true,
data: [
{type: "error", axisXType: "secondary", color: "#34dc00", dataPoints: [{ label: "Alpha", y: [ 0, 100 ] }, ]},
{type: "column", axisXType: "secondary", color: "#004ca0", dataPoints: [{ label: "Alpha", y: 71 }, ] },
{type: "column", axisXType: "secondary", color: "#ff0000", dataPoints: [{ label: "Alpha", y: 50 }, ] }
]
});
chart.render();
chart.data[0].set("stemThickness", chart.get("dataPointWidth") * 4 + 10);
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 360px; width: 100%;"></div>
In the code that you have shared, you are using column chart whereas in the screenshot shared it needs Stacked Bar Chart. Using Stacked Bar / Stacked Bar 100% & Error chart, you can achieve as shown in the screenshot shared. Below is the working code.
var chart = new CanvasJS.Chart("chartContainer", {
dataPointWidth: 70,
axisX: {
lineThickness: 0,
tickLength: 0,
labelFormatter: function(e) {
return "";
}
},
axisY: {
includeZero: true,
lineThickness: 0,
gridThickness: 0,
tickLength: 0,
labelFormatter: function(e) {
return "";
}
},
toolTip: {
shared: true
},
data: [{
type: "stackedBar100",
name: "Unique Opens: 33.3%",
showInLegend: true,
color: "#23a9e8",
dataPoints: [
{ x: 1, y: 33.3 }
]
}, {
type: "error",
name: "Unique Clicks: 33.3%",
showInLegend: true,
legendMarkerType: "square",
linkedDataSeriesIndex: 0,
stemThickness: 25,
whiskerThickness: 0,
color: "#336a84",
dataPoints: [
{ x: 1, y: [0, 33.3] }
]
}, {
type: "stackedBar100",
name: "Unique Opens: 66.7%",
showInLegend: true,
color: "#dfe3e4",
dataPoints: [
{ x: 1, y: 66.7 }
]
}]
});
chart.render();
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 100px; width: 100%;"></div>
I want two stacked column data in one chart using canvasjs like this:
I have currently done something like this with the options:
this achieves removing x axis and secondary y axis and showing two data together
{
animationEnabled: true,
options:{
scales: {
xAxes: [{ stacked:true}]
}
},
axisY: {
titleFontColor: "#4F81BC",
lineColor: "#4F81BC",
labelFontColor: "#4F81BC",
tickColor: "#4F81BC",
margin:24,
},
axisY2: {
gridThickness: 0,
tickLength: 0,
lineThickness: 0,
margin:24,
labelFormatter: function(){
return " ";
}
},
axisX:{
gridThickness: 0,
tickLength: 0,
lineThickness: 0,
margin:24,
labelFormatter: function(){
return " ";
}
},
toolTip: {
shared: true
},
legend: {
cursor:"pointer",
},
data: [{
type: "stackedColumn",
name: "Proven Oil Reserves (bn)",
legendText: "Proven Oil Reserves",
showInLegend: false,
dataPoints:[
{ y: 30.25 },
]
},
{
type: "stackedColumn",
name: "Oil Production (million/day)",
legendText: "Oil Production",
showInLegend: false,
dataPoints:[
{ y: 17.46 },
]
},
{
type: "stackedColumn",
name: "Oil Production (million/day)",
legendText: "Oil Production",
axisYType:"secondary",
margin:10,
showInLegend: false,
dataPoints:[
{ y: 10.46 },
]
},
{
type: "stackedColumn",
name: "Oil Production (million/day)",
legendText: "Oil Production",
axisYType:"secondary",
margin:10,
showInLegend: false,
dataPoints:[
{ y: 10.46 },
]
}
]
}
it produces the result like:
what I need is to
give margin between two datasets
able to label datasets with text over them as seen in the image above
give margin between two datasets
There will be gap between datapoints when the x-values are different.
able to label datasets with text over them as seen in the image above
You can use indexlabels. Please refer CanvasJS Docs for more info / examples. Below is an working example.
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
axisX:{
gridThickness: 0,
tickLength: 0,
lineThickness: 0,
labelFormatter: function(){
return "";
}
},
axisY: {
includeZero: true,
tickLength: 0,
lineThickness: 0,
gridColor: "#ddd",
labelFormatter: function(e) {
return "";
}
},
toolTip: {
shared: true
},
data: [{
type: "stackedColumn",
indexLabel: "RM xyz",
indexLabelFontColor: "#fff",
dataPoints: [
{ x: 1, y: 47, color: "#c63531" },
{ x: 2, y: 32, color: "#449fc7" }
]
}, {
type: "stackedColumn",
indexLabel: "RM xyz",
indexLabelFontColor: "#fff",
dataPoints:[
{ x: 1, y: 32, color: "#bb8786" },
{ x: 2, y: 27, color: "#74ab3e" }
]
}]
});
chart.render();
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
With a duplicate value in the data labels - Is there a way to draw the bubble on the first or second duplicate value in the bubble chart?
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
var ctx = document.getElementById("myChart");
var options = {responsive: true,
maintainAspectRatio: false,
};
var mixedChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["1", "2", "1", "4"], //Same Value on First and Third Position
datasets: [
//Lines
{
label: "First_Line",
type: "line",
borderColor: "#8e5ea2",
data: [5,10,7,12],
fill: false
}, {
label: "Second_Line",
type: "line",
borderColor: "#3e95cd",
data: [1,4,15,6],
fill: false
},
//Bubbles
{
label: "Bubble_One",
type: "bubble",
backgroundColor: "#8e5ea2",
data: [{ x: "2", y: 10, r: 15}],
},
{
label: "Bubble_Two",
type: "bubble",
backgroundColor: "#3e95cd",
backgroundColorHover: "#3e95cd",
data: [{x: ???, y: 6, r: 15}] //First "1" or Second "1" possible?
}
]
},
options: options
});
</script>
Something like "1"[0] unfortunately does not work.
You can not do it directly afaik but you can put an extra part in the label and filter it out of there with the callbacks for the tooltip and the axis:
<canvas id="myChart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
var ctx = document.getElementById("myChart");
var options = {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
offset: false,
ticks: {
callback: function(val) {
return this.getLabelForValue(val).split('-')[0]
}
}
}
},
plugins: {
tooltip: {
callbacks: {
label: (ttItem) => {
if (ttItem.dataset.type === "bubble") {
return `${ttItem.label}: (${ttItem.raw.x.split('-')[0]},${ttItem.raw.y})`
} else if (ttItem.dataset.type === "line") {
return `${ttItem.dataset.label}: ${ttItem.parsed.y}`
}
},
title: (ttItem) => (ttItem[0].label.split('-')[0])
}
}
}
};
var mixedChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["1-1", "2", "1-2", "4"], //Same Value on First and Third Position
datasets: [
//Lines
{
label: "First_Line",
type: "line",
borderColor: "#8e5ea2",
data: [5, 10, 7, 12],
fill: false
}, {
label: "Second_Line",
type: "line",
borderColor: "#3e95cd",
data: [1, 4, 15, 6],
fill: false
},
//Bubbles
{
label: "Bubble_One",
type: "bubble",
backgroundColor: "#8e5ea2",
data: [{
x: "2",
y: 10,
r: 15
}],
},
{
label: "Bubble_Two",
type: "bubble",
backgroundColor: "#3e95cd",
backgroundColorHover: "#3e95cd",
data: [{
x: "1-2",
y: 6,
r: 15
}] //First "1" or Second "1" possible?
}
]
},
options: options
});
</script>
I am looking to develop the following type of chart.
So far I have achieved the following result:
But I have the following problems and I have no idea how to perform them.
The days have 2 bar graphs in the form of a stack. The legend for these 2 graphs is the same so I am looking for it not to show duplicate at the top. These represent a percentage.
Each bar has a name: "Turn 1" and "Turn 2", so I would like them to be able to show when I hover over the charts along with their corresponding value.
Place on the right side of the "Y Axis" another text but this represents a whole number that is represented by the black line.
My source code is the following:
<!DOCTYPE html>
<html>
<head>
<title>Ejemplo</title>
<script src="https://www.chartjs.org/dist/2.9.4/Chart.min.js"></script>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
</style>
</head>
<body>
<div style="width: 75%">
<canvas id="canvas"></canvas>
</div>
<script>
var barChartData = {
labels: [
"Día 1",
"Día 2",
"Día 3",
"Día 4",
"Día 5",
"Día 6",
"Día 7",
"Día 8",
"Día 9",
"Día 10",
],
datasets: [
{
type: "line",
label: "Toneladas Provisionales",
borderColor: "#000000",
backgroundColor: "#000000",
borderWidth: 2,
fill: false,
data: [12.8, 28.53, 50.34, 50.87, 51.51, 53.12, 54.59],
},
{
label: "% UTILIZACION",
backgroundColor: "#3393df",
stack: "Turno 1",
data: [12.8, 28.53, 50.34, 50.87, 51.51, 53.12, 54.59],
},
{
label: "% COLAS LARGAS",
backgroundColor: "#e88967",
stack: "Turno 1",
data: [59, 10, 12, 8, 6, 17, 6],
},
{
label: "% COLAS DESCARGA",
backgroundColor: "#9d81bd",
stack: "Turno 1",
data: [10, 23, 13, 12, 8, 7, 11],
},
{
label: "% TALLER",
backgroundColor: "#b3b3b3",
stack: "Turno 1",
data: [19, 16, 10, 19, 18, 16, 11],
},
{
label: "% STAND BY + PARALIZACIONES",
backgroundColor: "#409640",
stack: "Turno 1",
data: [0, 23, 14, 11, 16, 7, 18],
},
{
label: "% TURNOS 0 PRODUCCION",
backgroundColor: "#ffdf00",
stack: "Turno 1",
data: [0, 0, 0, 0, 0, 0, 0],
},
{
label: "% UTILIZACION",
backgroundColor: "#3393df",
stack: "Turno 2",
data: [12.8, 28.53, 50.34, 50.87, 51.51, 53.12, 54.59],
},
{
label: "% COLAS LARGAS",
backgroundColor: "#e88967",
stack: "Turno 2",
data: [59, 10, 12, 8, 6, 17, 6],
},
{
label: "% COLAS DESCARGA",
backgroundColor: "#9d81bd",
stack: "Turno 2",
data: [10, 23, 13, 12, 8, 7, 11],
},
{
label: "% TALLER",
backgroundColor: "#b3b3b3",
stack: "Turno 2",
data: [19, 16, 10, 19, 18, 16, 11],
},
{
label: "% STAND BY + PARALIZACIONES",
backgroundColor: "#409640",
stack: "Turno 2",
data: [0, 23, 14, 11, 16, 7, 18],
},
{
label: "% TURNOS 0 PRODUCCION",
backgroundColor: "#ffdf00",
stack: "Turno 2",
data: [0, 0, 0, 0, 0, 0, 0],
},
],
};
var ctx = document.getElementById("canvas").getContext("2d");
var canvas = new Chart(ctx, {
type: "bar",
data: barChartData,
options: {
title: {
display: true,
text:
"Detalle de Tiempos de Utilización de Flota y Toneladas Transportadas por Turno del 1 al:",
},
legend: {
display: true,
},
tooltips: {
enabled: true,
},
responsive: true,
scales: {
xAxes: [
{
stacked: true,
},
],
yAxes: [
{
stacked: true,
ticks: {
min: 0,
max: this.max, // Your absolute max value
callback: function (value) {
return ((value / this.max) * 100).toFixed(0) + "%"; // convert it to percentage
},
},
scaleLabel: {
display: true,
labelString: "Porcentaje",
},
},
],
},
},
});
</script>
</body>
</html>
I'm trying to create a linear chart like a curve for different datasets but with start and end range for the x and y.
I want the start and end point of each dataset start from x y, how can convert the y line as values but takes labels? I tried to do something similar on the codepen but still need more to be similar to the image.
var data = {
labels: ["Group A", "Group B", "Group C", "Group D", "Group E"],
datasets: [
{
label: "Group A",
backgroundColor: gradient,
pointBackgroundColor: "white",
borderWidth: 1,
borderColor: "#911215",
data: [
{ x: 0, y: 0 },
{ x: 5, y: 5 }
]
},
{
label: "Group B",
backgroundColor: "green",
pointBackgroundColor: "white",
borderWidth: 1,
borderColor: "green",
data: [
{ x: 0, y: 0 },
{ x: 5, y: 5 },
{ x: 10, y: 10 }
]
},
{
label: "Group C",
backgroundColor: gradient,
pointBackgroundColor: "white",
borderWidth: 1,
borderColor: "#911215",
data: [
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 10, y: 10 },
{ x: 60, y: 60 },
{ x: 60, y: 10 }
]
},
{
label: "Group D",
backgroundColor: "blue",
pointBackgroundColor: "white",
borderWidth: 1,
borderColor: "blue",
data: [
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 60, y: 10 },
{ x: 0, y: 5 }
]
},
{
label: "Group E",
backgroundColor: "pink",
pointBackgroundColor: "white",
borderWidth: 1,
borderColor: "pink",
data: [
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 0 },
{ x: 0, y: 10 },
{ x: 0, y: 0 },
{ x: 0, y: 0 }
]
}
]
};
codepen