I need to recreate a chart very similar to this one:
While researching I found this example:
https://codepen.io/bencarmichael/pen/XeYJXJ
datasets: [
{
label: "American Express",
backgroundColor: "pink",
borderColor: "red",
borderWidth: 1,
data: [3, 5, 6, 7,3, 5, 6, 7] // I need labels on this values
}
]
It shows grouped bar charts. But it's lacking a label per bar. If it's not possible on Chart.js, it can be any other library.
use this code
View result in full screen mode
this is copied from the example you provided in you Question
var barChartData = {
labels: [
"Absence of OB",
"Closeness",
"Credibility",
"Heritage",
"M Disclosure",
"Provenance",
"Reliability",
"Transparency"
],
datasets: [
{
label: "American Express",
backgroundColor: "pink",
borderColor: "red",
borderWidth: 1,
data: [3, 5, 6, 7,3, 5, 6, 7],
},
{
label: "Mastercard",
backgroundColor: "lightblue",
borderColor: "blue",
borderWidth: 1,
data: [4, 7, 3, 6, 10,7,4,6]
},
{
label: "Paypal",
backgroundColor: "lightgreen",
borderColor: "green",
borderWidth: 1,
data: [10,7,4,6,9,7,3,10]
},
{
label: "Visa",
backgroundColor: "yellow",
borderColor: "orange",
borderWidth: 1,
data: [6,9,7,3,10,7,4,6]
}
]
};
var chartOptions = {
responsive: true,
legend: {
position: "top"
},
"hover": {
"animationDuration": 0
},
legend: {
"display": false
},
tooltips: {
"enabled": 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) {
debugger
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function (bar, index) {
var data = dataset.data[index];
ctx.font = '10pt Verdana';
ctx.save();
ctx.translate(0,500);
ctx.rotate(-0.5*Math.PI);
var rText = 'My test value ='+data ;
ctx.fillText(rText , 90, bar._model.x+5);
ctx.restore();
});
});
}
},
title: {
display: true,
text: "Chart.js Bar Chart"
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: "bar",
data: barChartData,
options: chartOptions
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="container" style="width: 75%;">
<canvas id="canvas"></canvas>
</div>
Related
Y have this issue:
User 1 repeats twice in two colors, gray and white.
Gray should not be seen
This problem starts when I put styles to the x axis, it repeats the labels.
is there any solution for this case?
The requirement is simply to change the color of the axis labels and ticks.
The gray bar is at the bottom, that is, it does not stack with the red and blue ones
var data = {
labels: ["User1", "User2"],
datasets: [
{
stack:1,
label: "TotalTime",
backgroundColor: "red",
borderWidth: 1,
data: [50, 50],
yAxisID:1
},
{
stack:1,
label: "TotalTime",
backgroundColor: "blue",
borderWidth: 1,
data: [40, 40],
yAxisID:1
},
{
label: "Leave",
backgroundColor: "rgba(191,191,191, 0.5)",
borderWidth: 1,
data: [100, 100],
yAxisID:1
},
],
};
var options = {
indexAxis: "y",
scales: {
y: {
ticks: {
color: "white",
font: {
size: 12,
},
},
stacked: true,
},
x: {
ticks: {
color: "white",
font: {
size: 12,
},
},
}
}
}
var ctx = document.getElementById("myChart").getContext("2d");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options: options
});
canvas{
background-color:black
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.6.2/dist/chart.min.js"></script>
<canvas id="myChart" width="500" height="300"></canvas>
It is because of your yAxisID, you dont define it but chart.js still makes a new axis for it since it isnt made by you with that id, so if you remove that or make it y which you have defined it doesnt make it again anymore
var data = {
labels: ["User1", "User2"],
datasets: [{
label: "TotalTime",
backgroundColor: "red",
borderWidth: 1,
data: [50, 50],
},
{
label: "TotalTime",
backgroundColor: "blue",
borderWidth: 1,
data: [40, 40],
},
{
label: "Leave",
backgroundColor: "rgba(191,191,191, 0.5)",
borderWidth: 1,
data: [100, 100],
},
],
};
var options = {
indexAxis: "y",
scales: {
y: {
ticks: {
color: "white",
font: {
size: 12,
},
},
stacked: true,
},
x: {
stacked: true,
ticks: {
color: "white",
font: {
size: 12,
},
},
}
}
}
var ctx = document.getElementById("myChart").getContext("2d");
var myBarChart = new Chart(ctx, {
type: 'bar',
data: data,
options: options
});
canvas {
background-color: black
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.6.2/dist/chart.min.js"></script>
<canvas id="myChart" width="500" height="300"></canvas>
I need to show the values on the top of bars using chartjs-node-canvas to create a PDF in Node
I have been able to recreate what I am looking in HTML but the plugin has the limitation of not accepting the "animation" property, for this reason I am looking to know if there is another way to do it in Node without the need for another external plugin. This is my current code
var ctx = document.getElementById("myChart");
var chart = new Chart(ctx, {
type: "bar",
data: {
labels: ["a", "b", "c", "d", "e", "f"],
datasets: [
{
type: "bar",
backgroundColor: "blue",
borderColor: "blue",
borderWidth: 1,
label: "promedio",
order: 1,
data: [60, 49, 72, 90, 100, 60]
},
{
type: "bar",
backgroundColor: "orange",
borderColor: "orange",
borderWidth: 1,
label: "promedio",
order: 1,
data: [40, 5, 20, 30, 10, 6]
},
{
type: "line",
label: "casos",
data: [25, 13, 30, 35, 25, 40],
lineTension: 0,
backgroundColor: "red",
borderColor: "red",
order: 0,
fill: false
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
animation: {
duration: 1,
onComplete: function () {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(16, 20, 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) {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y - 2);
});
});
}
},
legend: {
display: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<body>
<canvas id="myChart" width="400" height="200"></canvas>
</body>
Short answer is no, you either have to implement your own external inline plugin or use the datalabels plugin (https://chartjs-plugin-datalabels.netlify.app/samples/charts/bar.html) since there is no build in way to achieve this
I have a chart with multiple datasets. I want the label of a dataset from the legend to not be visible if all the values in a dataset are null. I've found some solutions but they were only working if data was declared in the initial configuration. In my case it is dynamically updated.
Here is the code:
self.initGraph = function () {
ctxWell = document.getElementById("wellChart").getContext('2d');
if (wellChart != undefined)
wellChart.destroy();
wellChart = new Chart(ctxWell, {
type: 'line',
data: {
labels: [],
datasets: [
{
backgroundColor: reportColor.Green,
borderColor: reportColor.Green,
label: 'Motor Frequency Hz',
yAxisID: 'y-axis-2',
data: [],
borderWidth: 1,
pointRadius: 0,
fill: false
},
{
backgroundColor: reportColor.Turquoise,
borderColor: reportColor.Turquoise,
label: 'Pump Discharge Pressure ' + helpers.getListSelectedValue(self.dischargePressureID(), self.pressureList()),
yAxisID: 'y-axis-1',
data: [],
borderWidth: 1,
pointRadius: 0,
fill: false
}
,
]
},
options: {
maintainAspectRatio: false,
animation: {
duration: 0
},
scales: {
yAxes: [
{
id: 'y-axis-1',
// stacked: true,
scaleLabel: {
display: true,
fontSize: 18,
labelString: helpers.getListSelectedValue(self.intakePressureID(), self.pressureList())
},
ticks: {
beginAtZero: true
}
},
{
id: 'y-axis-2',
position: 'right',
display: self.checkAxis(),
scaleLabel: {
display: self.checkAxis(),
fontSize: 18,
labelString: "Hz, " + helpers.getListSelectedValue(self.motorTemperatureID(), self.temperatureList())
},
ticks: {
beginAtZero: true
}
}
]
},
elements: {
line: {
tension: 0.000001
}
},
legend: {
display: true,
onClick: wellChartLegendClick,
}
},
}
});
wellChart.update();
};
self.updateWellDaily = function () {
var chart = wellChart;
chart.data.labels = [];
for (var j = 0; j < chart.data.datasets.length; j++) {
chart.data.datasets[j].data = [];
}
for (var i = 0; i < self.wellResults().length; i++) {
chart.data.labels.push(self.wellResults()[i].reportedTime);
chart.data.datasets[0].data.push(self.wellResults()[i].motorFrequency);
chart.data.datasets[1].data.push(self.wellResults()[i].pumpDischargePressure);
}
chart.update();
};
self.initGraph();
self.updateWellDaily();
The legend filter function can be used for this, if you tell it to hide labels where in the dataset all data is zeros it will update dynamicly, see example:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 0],
borderWidth: 1,
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
},
{
label: '# of Counts',
data: [1, 2, 3,4,5,2],
borderWidth: 1,
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
}
]
},
options: {
plugins: {
legend: {
labels: {
filter: (legendItem, chartData) => (!chartData.datasets[legendItem.datasetIndex].data.every(item => item === 0))
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
const chart = new Chart(ctx, options);
document.getElementById("tt").addEventListener("click", () => {
chart.data.datasets[1].data = [0, 0, 0, 0, 0, 0];
chart.update()
});
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<button id="tt">
change data
</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.1.0/chart.js" integrity="sha512-LlFvdZpYhQdASf4aZfSpmyHD6+waYVfJRwfJrBgki7/Uh+TXMLFYcKMRim65+o3lFsfk20vrK9sJDute7BUAUw==" crossorigin="anonymous"></script>
</body>
I have drawn a chart using Chartjs. I can explain the pixels I want to remove, but I think an image makes it a lot clearer:
Underneath is the code which generates this graph:
var options = {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5"],
datasets: [
{
borderWidth: 2,
borderColor: "#5d5d5d",
pointBorderColor: "#5d5d5d",
pointBackgroundColor: "#5d5d5d",
pointBorderWidth: 5,
type: 'line',
data: [26, 26, 33, 28, 30],
fill: false,
lineTension: 0
},
{
borderWidth: 3,
pointBorderColor: "#b8b8b8",
pointBackgroundColor: "#b8b8b8",
pointBorderWidth: 10,
type: 'line',
data: [26, 26, 29, 28, 29],
fill: false,
lineTension: 0
},
{
data: [0, 0, 0, 0, 0],
fill: false,
lineTension: 0
}
]
},
options: {
hover: {mode: null},
legend: {
display: false
},
tooltips: {enabled: false},
hover: {mode: null},
scales: {
xAxes: [{
gridLines: {
// drawBorder: false,
},
}],
yAxes: [{
display: false,
ticks: {
suggestedMin: 0,
max: 60,
beginAtZero: true
}
}]
}
}
}
var ctx = document.getElementById(elementID).getContext('2d');
new Chart(ctx, options);
Does anybody know how I can remove those unnecessary overlaying lines using Chart.js?
You can use the following chart plugin to remove those unnecessary overlaying lines :
Chart.plugins.register({
beforeDraw: function(chart) {
var ctx = chart.chart.ctx,
x_axis = chart.scales['x-axis-0'],
topY = chart.scales['y-axis-0'].top,
bottomY = chart.scales['y-axis-0'].bottom;
x_axis.options.gridLines.display = false;
x_axis.ticks.forEach(function(label, index) {
var x = x_axis.getPixelForValue(label);
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 1;
ctx.strokeStyle = x_axis.options.gridLines.color;
ctx.stroke();
ctx.restore();
});
}
});
ᴡᴏʀᴋɪɴɢ ᴅᴇᴍᴏ ⧩
Chart.plugins.register({
beforeDraw: function(chart) {
var ctx = chart.chart.ctx,
x_axis = chart.scales['x-axis-0'],
topY = chart.scales['y-axis-0'].top,
bottomY = chart.scales['y-axis-0'].bottom;
x_axis.options.gridLines.display = false;
x_axis.ticks.forEach(function(label, index) {
var x = x_axis.getPixelForValue(label);
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 1;
ctx.strokeStyle = x_axis.options.gridLines.color;
ctx.stroke();
ctx.restore();
});
}
});
var options = {
type: 'bar',
data: {
labels: ["1", "2", "3", "4", "5"],
datasets: [{
borderWidth: 2,
borderColor: "#5d5d5d",
pointBorderColor: "#5d5d5d",
pointBackgroundColor: "#5d5d5d",
pointBorderWidth: 5,
type: 'line',
data: [26, 26, 33, 28, 30],
fill: false,
lineTension: 0
}, {
borderWidth: 3,
pointBorderColor: "#b8b8b8",
pointBackgroundColor: "#b8b8b8",
pointBorderWidth: 10,
type: 'line',
data: [26, 26, 29, 28, 29],
fill: false,
lineTension: 0
}, {
data: [0, 0, 0, 0, 0],
fill: false,
lineTension: 0
}]
},
options: {
hover: {
mode: null
},
legend: {
display: false
},
tooltips: {
enabled: false
},
hover: {
mode: null
},
scales: {
xAxes: [{
gridLines: {
// drawBorder: false,
},
}],
yAxes: [{
display: false,
ticks: {
suggestedMin: 0,
max: 60,
beginAtZero: true
}
}]
}
}
}
var ctx = document.getElementById('canvas').getContext('2d');
new Chart(ctx, options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="canvas"></canvas>
I have a Pareto chart (using Chart.js Version: 2.0.2) and i need to display values inside of the bars and under the line.
Any help will be very appreciated:
This is the code (hope that it is useful for somebody):
<canvas id="canvas"></canvas>
<script type="text/javascript">
var data = {
labels: ["8","7","9","11","10"],
datasets: [{
type: "line",
label: "Acumulado",
borderColor: "#BA1E14",
backgroundColor: "#BA1E14",
pointBorderWidth: 5,
fill: false,
data: [34.04,57.45,76.60,89.36,100.00],
yAxisID: 'y-axis-2'
},{
type: "bar",
label: "Asistencia",
borderColor: "#56B513",
backgroundColor: "#56B513",
data: [16,11,9,6,5],
yAxisID: 'y-axis-1'
},{
type: "bar",
label: "Solución",
borderColor: "#000FAA",
backgroundColor: "#000FAA",
data: [16,11,9,6,5],
yAxisID: 'y-axis-1'
}]
};
var options = {
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: "Estaciones"
}
}],
yAxes: [{
type: "linear",
position: "left",
id: "y-axis-1",
stacked: true,
ticks: {
suggestedMin: 0
},
scaleLabel: {
display: true,
labelString: "Minutos"
}
},{
type: "linear",
position: "right",
id: "y-axis-2",
ticks: {
suggestedMin: 0,
callback: function(value) {
return value + "%";
}
},
scaleLabel: {
display: true,
labelString: "Porcentaje"
}
}]
}
};
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx, {
type: 'bar',
data: data,
options: options
});
};
</script>
Right now the chart looks like this:
And i need it to look like this:
This is the answer i developed (only in the options object):
var options = {
animation: {
onComplete: function() {
var ctx = this.chart.ctx;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
this.chart.config.data.datasets.forEach(function(dataset) {
ctx.font = "20px Arial";
switch (dataset.type) {
case "line":
ctx.fillStyle = "Black";
dataset.metaData.forEach(function(p) {
ctx.fillText(p._chart.config.data.datasets[p._datasetIndex].data[p._index], p._model.x, p._model.y - 20);
});
break;
case "bar":
ctx.fillStyle = "White";
dataset.metaData.forEach(function(p) {
ctx.fillText(p._chart.config.data.datasets[p._datasetIndex].data[p._index], p._model.x, p._model.y + 20);
});
break;
}
});
}
}
...
};
And this is the result:
I think since version 2.6.0 it's possible to Mix ChartTypes, like Bars and Lines
follow the instructions
A short example is 2 DataSet, one is bar type and other line type:
const data = {
labels: [
'January',
'February',
'March',
'April'
],
datasets: [{
type: 'bar',
label: 'Bar Dataset',
data: [10, 20, 30, 40],
borderColor: 'rgb(255, 99, 132)',
backgroundColor: 'rgba(255, 99, 132, 0.2)'
}, {
type: 'line',
label: 'Line Dataset',
data: [50, 50, 50, 50],
fill: false,
borderColor: 'rgb(54, 162, 235)'
}]
};
You just have to calculate the Pareto values and put on the Dataset Line Type