Chart.js - Draw horizontal line on horizontal bar chart - chart.js

I'm trying to achieve the following chart but i am not able to build it.
I was trying with this code (using https://github.com/chartjs/chartjs-plugin-annotation) but i think the solution is not perfect. The value of line "Días meta" needs to be configurable, so the line must be re-drawn as its value changes and the horizontal bar's dataset also changes.
The code:
<script>
var color = Chart.helpers.color;
var horizontalBarChartData = {
//labels: ['7', '6', '5', '4', '3', '2', '0'],
labels: ['5', '3', '2', '1'],
datasets: [{
label: 'QTA de bultos',
backgroundColor: color('#91B643').alpha(0.5).rgbString(),
borderColor: '#91B643',
borderWidth: 1,
data: [
2,
7,
4,
11
]
}]
};
$(document).ready(function () {
var ctx = document.getElementById('myChart').getContext('2d');
window.myHorizontalBar = new Chart(ctx, {
type: 'horizontalBar',
data: horizontalBarChartData,
options: {
// Elements options apply to all of the options unless overridden in a dataset
// In this case, we are setting the border of each horizontal bar to be 2px wide
elements: {
rectangle: {
borderWidth: 2,
}
},
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Horizontal Bar Chart'
},
hover: {
animationDuration: 0
},
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 = 'left';
ctx.textBaseline = 'center';
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.fillStyle = "#000";
ctx.fillText(data, bar._model.x + 5, bar._model.y);
});
});
}
},
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Días en Almacén'
},
gridLines: {
display: false
}
}
],
xAxes: [{
gridLines: {
display: true
},
ticks: {
beginAtZero: true
}
}
]
},
annotation: {
annotations: [{
type: 'line',
mode: 'horizontal',
scaleID: 'x-axis-0',
value: 1,
borderColor: 'rgb(75, 192, 192)',
borderWidth: 4,
label: {
enabled: true,
content: 'Días meta: 999'
}
}]
}
}
});
});
</script>
Example - With original dataset
Example - With change only one value of dataset
Any help will be appreciated, thanks =)

Related

Chart.Js vers2 multiline to version 3

I try to create a multi axis chart using chart.js ver 3.6.0 but it look nothing like the one displayed in their example found here chart
This is the code I use.
<canvas id="canvas"></canvas>
<script>
const ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.height = 200;
const labels = "11/1/2021,11/2/2021,11/3/2021,11/4/2021,11/5/2021,11/6/2021,11/7/2021,11/8/2021,11/9/2021,11/10/2021";
const data = {
labels: labels,
datasets: [
{
label: "South",
data: "6,4,2,4,3,1,0,9,3,0",
borderColor: "#0d47a1",
backgroundColor: "#2196f3",
yAxisID: "y",
},
{
label: "North",
data: "72,97,88,143,102,0,0,153,100,0",
borderColor: "#e65100",
backgroundColor: "#ff9800",
yAxisID: "y1",
},
],
};
const config = {
type: "line",
data: data,
options: {
responsive: true,
interaction: {
mode: "index",
intersect: false,
},
stacked: false,
plugins: {
title: {
display: true,
text: "Test",
},
},
scales: {
y: {
type: "linear",
display: true,
position: "left",
},
y1: {
type: "linear",
display: true,
position: "right",
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
x: {
ticks: {
maxRotation: 65,
minRotation: 65,
fontSize: 11,
},
},
},
},
};
window.myLine = new Chart(ctx, config);
</script>
Why is the lines not connected, and why is the y axis not displaying each datasets max value?
Mine looks like this..
This is because you provide the labels and data as strings while it should be an array with strings for the labels, same goes for the data field:
<canvas id="canvas"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
<script>
const ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.height = 200;
const labels = ['11/1/2021', '11/2/2021', '11/3/2021', '11/4/2021', '11/5/2021', '11/6/2021', '11/7/2021', '11/8/2021', '11/9/2021', '11/10/2021'];
const data = {
labels: labels,
datasets: [{
label: 'South',
data: ['6', '4', '2', '4', '3', '1', '0', '9', '3', '0'],
borderColor: '#0d47a1',
backgroundColor: '#2196f3',
yAxisID: 'y',
},
{
label: 'North',
data: ['72', '97', '88', '143', '102', '0', '0', '153', '100', '0'],
borderColor: '#e65100',
backgroundColor: '#ff9800',
yAxisID: 'y1',
}
]
};
const config = {
type: 'line',
data: data,
options: {
responsive: true,
interaction: {
mode: 'index',
intersect: false,
},
stacked: false,
plugins: {
title: {
display: true,
text: 'Test'
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
},
y1: {
type: 'linear',
display: true,
position: 'right',
// grid line settings
grid: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
},
x: {
ticks: {
maxRotation: 65,
minRotation: 65,
fontSize: 11
}
}
}
},
};
new Chart(ctx, config);
</script>

How to make multiple horizontal bar chartjs

I want to make horizontal bar chart using chartjs in react like this: chart i want to make
but i end up doing like this chart i make
can someon help me please, im new in react and chartjs
Here's the continuation of this post: How to make labels on both side from horizontal bar chart js
here's what i code:
this the data:
export const dataPasienKeluarMasuk = {
type: 'bar',
labels: [
[0, 1, 2, 3,4], // expect output 0 - 4
[5, 6, 7, 8, 9], // expect output 5 - 9
[10, 14], // ext..
[15, 19],
[20, 24],
[25, 29],
[30, 34],
],
datasets: [
{
label: 'Pasien Masuk',
xAxisID: 'A',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
xAxisID: 'A',
data: [-100, -90, -80, -70, -60],
backgroundColor: 'blue',
},
],
}
here's the chart:
import { HorizontalBar } from 'react-chartjs-2'
import { dataPasienKeluarMasuk } from ...blabla
<HorizontalBar
data={dataPasienKeluarMasuk}
height={227}
options={{
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
display: true,
position: 'bottom',
},
scales: {
xAxes: [
{
id: 'A',
position: 'left',
},
],
},
}}
/>
You should define both axes as stacked:
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true
}]
}
In order to see only positive values displayed on the x-axis ticks, you need to define a ticks.callback function on the x-axis.
ticks: {
callback: value => Math.abs(value)
}
To have only positive values displayed in the tooltips, you further need to define a tooltips.callback.label functions as shown below.
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
let ds = data.datasets[tooltipItem.datasetIndex];
return ds.label + ': ' + Math.abs( ds.data[tooltipItem.index]);
}
}
},
Please take a look at the runnable code snippet below and see how it works (this is a pure Chart.js solution but it should easily be adaptable to react-chart.js).
new Chart(document.getElementById('canvas'), {
type: 'horizontalBar',
data: {
labels: ['a', 'b', 'c', 'd', 'e'],
datasets: [{
label: 'Pasien Masuk',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
data: [-100, -90, -80, -70, -60],
backgroundColor: 'blue',
},
]
},
options: {
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
position: 'bottom',
},
tooltips: {
callbacks: {
label: (tooltipItem, data) => {
let ds = data.datasets[tooltipItem.datasetIndex];
return ds.label + ': ' + Math.abs( ds.data[tooltipItem.index]);
}
}
},
scales: {
xAxes: [{
stacked: true,
ticks: {
callback: value => Math.abs(value)
}
}],
yAxes: [{
stacked: true
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas"></canvas>
this snippet is based from uminder's answer
new Chart(document.getElementById('canvas'), {
type: 'horizontalBar',
data: {
labels: ['a', 'b', 'c', 'd', 'e'],
datasets: [{
label: 'Pasien Masuk',
data: [100, 90, 80, 70, 60],
backgroundColor: 'red',
},
{
label: 'Pasien Keluar',
data: [-100, -90, -80, -70, -60],
backgroundColor: 'blue',
},
]
},
options: {
responsive: true,
title: {
display: true,
text: 'Data Pasien Keluar Masuk',
fontSize: 20,
},
legend: {
display: true,
position: 'bottom',
},
scales: {
xAxes: [{
stacked: true,
ticks: {
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return value < 0? -(value) : value
}
}
}],
yAxes: [{
stacked: true
}]
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
var value = tooltipItem.xLabel;
value = value < 0? -(value) : value
return label + ': ' + value;
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas"></canvas>

How can I show chartjs datalabels only last bar?

I need to show the last bar value only. like this image:
I try this code but it shows all values.
var dataX = {
labels: [['Personne', 'seule'], ['Couple sans', 'enfant'], ['Couple avec', 'enfant(s)'], ['Famille', 'monoparentale'], 'Autres'],
datasets: [{
label: 'Data 1',
data: [33,28,25,8,2.5],
backgroundColor: '#00BBF1',
borderWidth: 0
},
{
label: 'Data 2',
data: [29,30,30,8,2],
backgroundColor: '#3CC6F4',
borderWidth: 0
},
{
label: 'Data 3',
data: [41,22,22,11,3],
backgroundColor: '#92D9F8',
borderWidth: 0
}]
};
var optionsX = {
tooltips: {
enabled: false
},
responsive: true,
maintainAspectRatio: false,
legend: false,
scales: {
xAxes: [{
gridLines : {
color: "#fff"
},
}],
yAxes: [{
gridLines : {
display : false
},
ticks: {
min: 0,
max: 50,
stepSize: 10,
callback: function(value) {
return value + "%"
},
}
}]
},
plugins: {
datalabels: {
color: '#59595B',
font: {
weight: 'bold',
size: 14,
},
align: 'end',
anchor: 'end',
formatter: function(value, context) {
return value +'%';
}
}
},
};
var ctx = document.getElementById('chart-one');
var myChart = new Chart(ctx, {
type: 'bar',
data: dataX,
options: optionsX
});
You can change the plugins.datalabels.formatter function as follows:
plugins: {
...
datalabels: {
formatter: (value, context) => context.datasetIndex == 2 ? value + '%' : ''
}
}
Please take a look at your amended code below and see how it works.
var dataX = {
labels: [
['Personne', 'seule'],
['Couple sans', 'enfant'],
['Couple avec', 'enfant(s)'],
['Famille', 'monoparentale'], 'Autres'
],
datasets: [{
label: 'Data 1',
data: [33, 28, 25, 8, 2.5],
backgroundColor: '#00BBF1',
borderWidth: 0
},
{
label: 'Data 2',
data: [29, 30, 30, 8, 2],
backgroundColor: '#3CC6F4',
borderWidth: 0
},
{
label: 'Data 3',
data: [41, 22, 22, 11, 3],
backgroundColor: '#92D9F8',
borderWidth: 0
}
]
};
var optionsX = {
tooltips: {
enabled: false
},
responsive: true,
maintainAspectRatio: false,
legend: false,
scales: {
xAxes: [{
gridLines: {
color: "#fff"
},
}],
yAxes: [{
gridLines: {
display: false
},
ticks: {
min: 0,
max: 50,
stepSize: 10,
callback: function(value) {
return value + "%"
},
}
}]
},
plugins: {
datalabels: {
color: '#59595B',
font: {
weight: 'bold',
size: 14,
},
align: 'end',
anchor: 'end',
formatter: (value, context) => context.datasetIndex == 2 ? value + '%' : ''
}
},
};
var ctx = document.getElementById('chart-one');
var myChart = new Chart(ctx, {
type: 'bar',
data: dataX,
options: optionsX
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
<canvas id="chart-one"></canvas>

Adding line over stacked line chart with ChartJS

I'm trying to recreate this below chart with a stacked option on my background lines
But my attempts were unsuccessful with this image below as result
$(function() {
var areaChartCanvas = $('#areaChart').get(0).getContext('2d')
var areaChartData = {
labels: ['', '', ''],
datasets: [{
backgroundColor: 'transparent',
borderColor: 'black',
pointRadius: false,
data: [32, 12, 28],
type: 'line'
}, {
backgroundColor: 'red',
pointRadius: false,
data: [20, 20, 20]
}, {
backgroundColor: 'orange',
pointRadius: false,
data: [40, 40, 40]
}, {
backgroundColor: 'cyan',
pointRadius: false,
data: [60, 60, 60]
}]
}
var areaChartOptions = {
maintainAspectRatio: false,
responsive: true,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display: true,
}
}],
yAxes: [{
gridLines: {
display: true,
},
stacked: true
}]
}
}
var areaChart = new Chart(areaChartCanvas, {
type: 'line',
data: areaChartData,
options: areaChartOptions
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<canvas id="areaChart" style="height:250px"></canvas>
ideally, I want to be able to create 'AREAS' with different colors that will be stacked according to the interval I pass to it.
e.g:
cyan - 20
orange - 20
red - 20
but currently, I'm doing
cyan - 60
orange - 40
red - 20
If I understand you correctly, I thought about different approach and extends the chart with Plugin[1] (Inspired by https://stackoverflow.com/a/49303362/863110)
Chart.pluginService.register({
beforeDraw: function (chart, easing) {
if (chart.config.options.fillColor) {
var ctx = chart.chart.ctx;
var chartArea = chart.chartArea;
ctx.save();
let delta = 0;
const chartHeight = chartArea.bottom - chartArea.top;
const bottomBarHeight = chart.height - chartHeight - chartArea.top;
chart.config.options.fillColor.map(color => {
const colorHeight = chartHeight * (color[0] / 100);
const colorBottom = chartArea.bottom + colorHeight;
ctx.fillStyle = color[1];
const x = chartArea.left,
y = chart.height - bottomBarHeight - colorHeight - delta,
width = chartArea.right - chartArea.left,
height = colorHeight;
delta += height;
ctx.fillRect(x, y, width, height);
ctx.restore();
})
}
}
});
var chartData = {
labels: ['a', 'b', 'c', 'd'],
datasets: [{
label: 'value',
borderColor: 'blue',
data: [30, 50, 25, 10]
}]
};
var ctx = document.getElementById("myChart").getContext("2d");
var myBar = new Chart(ctx, {
type: 'line',
data: chartData,
options: {
scales: {
yAxes: [{ ticks: { max: 60 } }]
},
legend: { display: false },
fillColor: [
[20, 'red'],
[20, 'blue'],
[20, 'green'],
[20, 'pink'],
[20, 'yellow'],
]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="myChart" height="300" width="500"></canvas>
https://jsbin.com/lisuvuq/2/edit?js,output
[1] - With Plugin you can custom the chart's behaviour. When you use Plugin you get an API so you can "listen" to life cycle events of the chart (beforeDraw for example) and call your own code. The API calls your function and gives you data about the chart so you can use it in your code.In this example, we're using the API to (1) Run a code before the chart been drawing (2) Using the data to calculate the areas of the different colors. (3) Draw additional shapes (ctx.fillRect) based on the calculation.

Remove excess lines on y axis using chartjs

I wonder how to remove the excess lines on the line chart. I tried to set drawborder to false but of course it just remove the all lines to the axis. I just wanted get rid of the unwanted vertical lines that points to the y axis labels like the image below with red mark.
Template:
<d-chartrecord
:chart-data="datacollection"
v-bind:options="options"
:height="200"
></d-chartrecord>
Script:
export default {
data () {
return {
datacollection: {},
options: {
responsive: true,
legend: {
display: false,
},
scales: {
xAxes: [{
gridLines: {
display: true,
color: '#D7D7D7'
},
ticks: {
fontSize: 8,
beginAtZero: true
},
gridLines: {
display: true,
}
}],
yAxes: [{
display: true,
ticks: {
fontSize: 8,
beginAtZero: true,
stepSize: 50,
maxTicksLimit: 3
}
}],
}
},
}
},
mounted () {
this.putData()
},
methods: {
putData () {
this.datacollection = {
labels: ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
datasets: [{
lineTension: 0,
radius: 4,
borderWidth: 1,
borderColor: '#F2A727',
pointBackgroundColor:[ '#fff', '#fff', '#fff', '#fff', '#fff', '#F2A727'],
backgroundColor: 'transparent',
data: [this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt()]
}]
}
},
getRandomInt () {
return Math.floor(Math.random() * (95)) + 5
}
}
}
In chart.js, gridLines provides an option tickMarkLength to disable the length beyond the axes, Eg:
yAxes: [{
gridLines: {
tickMarkLength: 0,
},
}]
xAxes: [{
gridLines: {
tickMarkLength: 0,
},
}]
Unfortunately, there isn't any native functionality for this in ChartJS at the moment. You would rather need to create a chart plugin to achieve that.
ᴘʟᴜɢɪɴ (ᴅʀᴀᴡ x-ᴀxɪꜱ ɢʀɪᴅ-ʟɪɴᴇꜱ)
­
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) {
if (index === 0) return;
var x = x_axis.getPixelForValue(label);
ctx.save();
ctx.beginPath();
ctx.strokeStyle = x_axis.options.gridLines.color;
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.stroke();
ctx.restore();
});
}
});
* place this at the top of your script
ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩
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; // hide original grid-lines
// loop through x-axis ticks
x_axis.ticks.forEach(function(label, index) {
if (index === 0) return;
var x = x_axis.getPixelForValue(label);
ctx.save();
ctx.beginPath();
ctx.strokeStyle = x_axis.options.gridLines.color;
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.stroke();
ctx.restore();
});
}
});
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
datasets: [{
label: 'LINE',
data: [3, 1, 4, 2, 5],
backgroundColor: 'rgba(0, 119, 290, 0.2)',
borderColor: 'rgba(0, 119, 290, 0.6)',
fill: false,
tension: 0
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
stepSize: 1
},
gridLines: {
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>
in Chart.js (I'm using version 2.9), gridLines also provides an option to disable the tick mark : drawTicks.
scales: {
xAxes: [{
gridLines:{
drawTicks: false
}
}]
}