chart.js v3: How to align gridlines with stepsizes? - reactjs

Expected:
enter image description here
Current:
enter image description here
I want to have stepsizes and gridlines in the same line and some padding
How can i achieve that with chart.js v3
scales: {
y: {
stacked: true,
grid: {
offset: true,
display: true,
drawBorder: false,
drawOnChartArea: true,
borderDashOffset: 25,
borderColor: "#d1d2db",
borderWidth: 0.8800000000000001,
color: "#d1d2db",
},
min: 0,
max: max,
ticks: {
// forces step size to be 25 units
stepSize: 25,
beginAtZero: true,
callback: callback,
max: max,
},
title: {
display: false,
text: "Y axis title",
},
},
x: {
grid: {
offset: true,
display: true,
drawBorder: false,
drawOnChartArea: false,
drawTicks: false,
tickLength: 0,
// borderDash: [0, 1],
// borderDashOffset: 0,
borderColor: "#d1d2db",
// borderWidth: 0.8800000000000001,
color: "#d1d2db",
},
},
},
Btw, is it also possible to have perpendiculars from data points to x-axis as shown in expected design ?

To have the horizontal grid lines aligned with the y labels, define options.scales.y.grid.offset: false or omit the option.
For the vertical lines from the bottom of the chart up to individual data points, you can use the Plugin Core API. In the afterDraw hook for example, you can draw the lines directly on the canvas using the CanvasRenderingContext2D.
Please take a look at your amended and runnable code and see how it works.
new Chart('chart', {
type: 'line',
plugins: [{
afterDraw: chart => {
var ctx = chart.ctx;
ctx.save();
var xAxis = chart.scales.x;
var yAxis = chart.scales.y;
const data = chart.data.datasets[0].data;
xAxis.ticks.forEach((v, i) => {
var x = xAxis.getPixelForTick(i);
var yTop = yAxis.getPixelForValue(data[i]);
ctx.strokeStyle = '#aaaaaa';
ctx.beginPath();
ctx.moveTo(x, yAxis.bottom);
ctx.lineTo(x, yTop);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
labels: [1, 2, 3, 4, 5, 6, 7],
datasets: [{
label: 'My Data',
data: [65, 59, 80, 81, 56, 55, 68],
borderColor: '#0a0'
}]
},
options: {
scales: {
y: {
stacked: true,
grid: {
display: true,
drawBorder: false,
drawOnChartArea: true,
borderDashOffset: 25,
borderColor: "#d1d2db",
borderWidth: 0.8800000000000001,
color: "#d1d2db",
},
min: 0,
ticks: {
stepSize: 25,
beginAtZero: true,
},
title: {
display: false,
text: "Y axis title",
},
},
x: {
grid: {
offset: true,
display: true,
drawBorder: false,
drawOnChartArea: false,
drawTicks: false,
tickLength: 0,
borderColor: "#d1d2db",
color: "#d1d2db",
},
},
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<canvas id="chart" width="400" height="95"></canvas>

Related

react-chartjs-2 hiding axis label

I'm trying to hide yAxis labels. I tried display: false property, but that didn't work.
My code below:
export const options = {
responsive: true,
interaction: { includeInvisible: true, intersect: false },
tooltip: {
backgroundColor: "rgba(0, 0, 0, 0.3)",
displayColors: false,
multiKeyBackground: "rgba(0, 0, 0, 0)",
},
scale: {
y1: {
min: 0,
ticks: {
count: 5,
},
grid: { borderDash: [3], color: "rgb(126,126,126)", tickLength: 0 },
},
y2: {
display: false,
position: "right",
max: Math.max(...BTCPrices.map((el) => el.Volume)) * 10,
ticks: {
count: 5,
},
},
x: {
ticks: {},
},
},
plugins: {
legend: {
display: false,
},
},
};
here's the image describing the problem:
Thanks for helping!
This is because your config is not getting picked up, you putted your scale config in the options.scale namespace white it needs to be configured in the options.scales so you need to add an extra s at the end
This is how I manage to get rid of the labels, I think in your case instead of Y its gonna be y2
y: {
ticks: {
display: false, //this will remove only the label
},
},

react-chart-js2 Showing Negative Axis when dataset contains all 0's

I am using react-chart-js2#3.3.0 with chart.js#3.6.2
When my dataset contains all 0s, the y-axis scales from -1 to 1 as such:
See Image
How do I make it start at 0 regardless? There seems to be a workaround for this: here and here but these solutions did not work for me. Basically, the workaround is to include a max in the ticks but it appears to just ignore it. I also tried upgrading to react-chart-js2#4 but for some reason it breaks so I reverted it back to 3.3.0.
Here is my options object:
const options = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false,
},
},
layout: {
padding: 0,
},
scales: {
xAxes: [
{
gridLines: {
display: false,
drawBorder: false,
},
ticks: {
padding: 18,
fontColor: theme.palette.text.secondary,
},
},
],
yAxes: [
{
gridLines: {
borderDash: [6],
borderDashOffset: [0],
display: false,
color: theme.palette.divider,
drawBorder: false,
zeroLineBorderDash: [6],
zeroLineBorderDashOffset: [0],
zeroLineColor: theme.palette.divider,
},
ticks: {
padding: 12,
fontColor: theme.palette.text.secondary,
beginAtZero: true,
min: 0,
max: 100,
},
},
],
},
tooltips: {
enabled: true,
mode: "nearest",
intersect: false,
caretSize: 6,
displayColors: false,
yPadding: 8,
xPadding: 16,
borderWidth: 4,
borderColor: theme.palette.common.black,
backgroundColor: theme.palette.common.black,
titleFontColor: theme.palette.common.white,
bodyFontColor: theme.palette.common.white,
footerFontColor: theme.palette.common.white,
callbacks: {
title: () => {},
label: (tooltipItem) => {
return `New Users: ${tooltipItem.yLabel}`;
},
},
},
};
the min and max have to be outside of the ticks:
y: { ticks: { }, min: 0, max: 100 }

CoreUI Chart type Bar- clickable bars to link to another page

I'm looking to create a drilldown using the CChartBar available in the CoreUI documentation here: https://coreui.io/react/docs/3.3/components/CCharts/
I need to be able to get the month from the bar that is clicked, and when the bar is clicked, it needs to take the user to another page. How do I get the information? How to I make each bar clickable to send the user to the table page?
Currently here is the html
<div className="chart-container">
<CChartBar
datasets={[
{
label: "Expected Expirations",
type: "bar",
data: expectedExpirations,
backgroundColor: "#949fe8",
borderColor: "blue",
fill: true,
order: 2,
},
{
label: 'Actual Expirations',
type: "bar",
data: actualExpirations,
backgroundColor: '#556ad1',
borderColor: "blue",
fill: true,
order: 1,
},
{
label: 'Target Expirations',
backgroundColor: '#352c2c',
data: targetExpirations,
type: "line",
borderColor: "black",
fill: true,
order: 0,
borderWidth: 2,
fill: "#352c2c",
pointBackgroundColor: "#352c2c",
lineTension: 0,
}
]}
labels={dateLabels}
onClick={(event) => drillDown(event)}
options={{
maintainAspectRatio: false,
responsive: true,
tooltips: {
enabled: true,
},
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: "Month"
}
}],
yAxes: [{
ticks: {
stacked: true,
beginAtZero: true,
stepValue: 10,
max: maxOfAllExpirations
},
scaleLabel: {
display: true,
labelString: "Number of Lease Expirations"
}
}]
},
}}
/>
I would like to be able to click on the bar, and get the data that is being charted, so I can pass the month to another page.
You can use the onClick function for this:
var options = {
type: 'bar',
data: {
labels: ["December 2020", "Januarie 2021", "Feb 2021", "March 2021", "April 2021", "May 2021"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 3, 3],
backgroundColor: 'pink'
}]
},
options: {
onClick: (evt, activeEls) => {
console.log(activeEls[0]._model.label)
console.log(activeEls[0]._model.label.split(" ")[0])
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
</body>
<div className = "chart-container" >
<CChartBar
datasets = {
[{
label: "Expected Expirations",
type: "bar",
data: expectedExpirations,
backgroundColor: "#949fe8",
borderColor: "blue",
fill: true,
order: 2,
},
{
label: 'Actual Expirations',
type: "bar",
data: actualExpirations,
backgroundColor: '#556ad1',
borderColor: "blue",
fill: true,
order: 1,
},
{
label: 'Target Expirations',
backgroundColor: '#352c2c',
data: targetExpirations,
type: "line",
borderColor: "black",
fill: true,
order: 0,
borderWidth: 2,
fill: "#352c2c",
pointBackgroundColor: "#352c2c",
lineTension: 0,
}
]
}
labels = {
dateLabels
}
onClick = {
(event) => drillDown(event)
}
options = {
{
onClick: (evt, activeEls) => {
console.log(activeEls[0]._model.label)
console.log(activeEls[0]._model.label.split(" ")[0])
},
maintainAspectRatio: false,
responsive: true,
tooltips: {
enabled: true,
},
scales: {
xAxes: [{
stacked: true,
scaleLabel: {
display: true,
labelString: "Month"
}
}],
yAxes: [{
ticks: {
stacked: true,
beginAtZero: true,
stepValue: 10,
max: maxOfAllExpirations
},
scaleLabel: {
display: true,
labelString: "Number of Lease Expirations"
}
}]
},
}
}
/>
``

How to set X coordinate for each bar with react chart js 2?

I want to make a chart with min and max vertical lines and bars between them. I can't find information how to set bars' X coordinate or make custom line plot with vertical 'bars' instead of points.
And also I don't understand how to scale X axis, why MAX is left-side MIN? Min=22.5, Max=24.5
let plot_options = {
showScale: true,
pointDot: true,
showLines: true,
maintainAspectRatio: false,
annotation: {
annotations: [
{
type: 'line',
mode: 'vertical',
scaleID: 'y-axis-0',
value: min,
borderColor: 'red',
borderWidth: 2,
label: {
backgroundColor: 'red',
content: 'Min',
enabled: true,
},
},
{
type: 'line',
mode: 'vertical',
scaleID: 'y-axis-0',
value: max,
borderColor: 'red',
borderWidth: 2,
label: {
backgroundColor: 'red',
content: 'MAX',
enabled: true,
},
},
]
},
title: {
display: true,
text: plotHeader,
},
responsive: true,
legend: {
display: false,
},
scales: {
xAxes: [{
scaleLabel: {
display: true,
labelString: labelx
},
ticks: {
min: min,
max: max
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: labely
},
ticks: {
beginAtZero: true,
},
}]
},
}
data = {
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
labels: labels,
datasets: [{
data: values,
borderColor: BLUE,
backgroundColor: BLUE
}]
}
<Bar options={plot_options} data={data} plugins={ChartAnnotation} />
That's what I expect:
This solution is based on this answer for the positioning of the bars on a linear x-axis.
You can further use the Plugin Core API to draw the vertical min and max lines with their labels directly on the canvas. The API offers a number of hooks that can be used to perform custom code. In your case, you could use the afterDraw hook together with CanvasRenderingContext2D.
Please take a look at the runnable code below and see how it works. It should not be too hard to make similar code work with react-chartjs-2.
new Chart("chart", {
type: 'bar',
plugins: [{
afterDraw: chart => {
let ctx = chart.chart.ctx;
ctx.save();
let xAxis = chart.scales['x-axis-0'];
let yAxis = chart.scales['y-axis-0'];
let dataset = chart.data.datasets[0];
[dataset.min, dataset.max].forEach((v, i) => {
var x = xAxis.getPixelForValue(+v * 1000);
ctx.fillStyle = 'red';
ctx.font = '14px Arial';
ctx.textAlign = 'center';
ctx.fillText(i == 0 ? 'Min' : 'Max', x, yAxis.top + 14);
ctx.fillStyle = 'gray';
ctx.font = '12px Arial';
ctx.fillText(v, x, yAxis.bottom + 20);
ctx.beginPath();
ctx.moveTo(x, yAxis.top + 20);
ctx.strokeStyle = 'red';
ctx.lineTo(x, yAxis.bottom + 3);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
datasets: [{
min: 22.5,
max: 24.5,
data: [
{ x: '22.83', y: 18 },
{ x: '23.17', y: 15 },
{ x: '23.44', y: 13 },
{ x: '24.32', y: 20 }
],
borderColor: 'blue',
backgroundColor: 'blue',
barThickness: 20
}]
},
options: {
legend: {
display: false,
},
scales: {
xAxes: [{
offset: true,
type: 'time',
time: {
parser: 'X',
unit: 'millisecond',
displayFormats: {
millisecond: 'X'
}
},
ticks: {
source: 'data',
min: '22.5',
callback: (v, i, values) => values[i].value / 1000
},
gridLines: {
display: false
},
}],
yAxes: [{
ticks: {
beginAtZero: true,
max: 22,
stepSize: 2
}
}]
}
}
});
canvas {
max-width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"></script>
<canvas id="chart" height="200"></canvas>

Chartjs: Draw chart with only yAxis zero tick

Hell, all,
I would like to draw the chart like this:
Currently, I can use afterBuildTicks to get only zero yAxis. But the problem is that the whole other ticks were removed also. So Not sure if we have a way to draw zero tick and keep other ticks hidden except the label.
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ['Value 1', 'Value 2', 'Value 3', 'Value 4'],
datasets: [{
label: "Dataset",
data: [20, 15, 27, 18],
backgroundColor: 'rgba(54, 162, 235,0.5)',
}],
},
options: {
responsive: true,
elements: {
line: {
fill: false
}
},
scales: {
xAxes: [
{
position: 'top',
display: true,
gridLines: {
display: true,
},
stacked: true,
ticks: {
fontColor: "#C4C4C4",
fontSize: 10,
}
}
],
yAxes: [
{
type: 'linear',
display: true,
position: 'right',
id: 'y-axis-1',
gridLines: {
display: true,
},
labels: {
show: true
},
stacked: false,
ticks: {
fontColor: "#C4C4C4",
fontSize: 10,
precision: 0,
suggestedMax: 100,
suggestedMin: -100
},
afterBuildTicks:function (axis) {
axis.ticks = [0]
}
}
]
},
tooltips: {
mode: 'label',
bodySpacing: 10,
titleMarginBottom: 10,
titleFontSize: 14,
titleFontStyle: 'bold',
footerAlign: 'right',
callbacks: {
label: (tooltipItem, data) => {
const label = data.datasets[tooltipItem.datasetIndex].label || ''
const value = tooltipItem.value
return ` ${label}: ${value}`
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<canvas id="myChart" height="100"></canvas>
Thanks so much
I found the solution that use: gridLines options to draw chart with width is zero:
gridLines: {
display: true,
tickMarkLength: 10,
lineWidth: 0
}

Resources