How to make custom Y values in chart.js - reactjs

I'm currently working on project in react.js. I'm trying to get some data to appear using chart.js but am having some difficulties. I'm trying to create a custom label for my difficulty chart.
Trying to have a difficulty of easy, medium, or hard display on the y value that corresponds with the numbers 0, 1, and 2 But the 2 value is getting skipped over in my chart.
Code:
const yLabels = {
0:'easy',
1.0:'medium',
2.0:'hard',
}
const createChart = (data) => {
return (
<div className="chart">
<h1>{data.name}</h1>
<div >
<div >
<Line
width={600}
height={200}
data={data}
options={{
responsive: true,
scaleShowValues: true,
scales: [
{
ticks:{
autoSkip: true,
stepSize: 1,
startAtZero: true,
callback: function(value, index, ticks){
console.log(ticks)
return `${yLabels[value]}`
}
}
}
],
plugins: {
title: {
fontSize: 30,
display: true,
font: { size: 20 }
},
legend: {
labels: {
font: { size: 15 }
}
}
},
}}
/>
</div>
</div>
</div>
)
1. List item
}
What can I try next?

Related

custom y axis with react-chartjs-2 library and typscript

I am trying to do up a custom y-axis to convert 1 to a custom string. E.g. 1 is "Apple"
Been trying different solutions and none seems to work for the "scales" option. I doing its on react typescript.
Also, I am very confused about whether to use [], "y", "yAxis" or "yAxes".
const opt = {
plugins: {
legend: {
display: false,
labels: {
color: 'rgb(255, 99, 132)'
}
},
scales: {
yAxes: [{
ticks: {
beginAtZero: false,
min: 0,
stepSize: 2,
callback: function(value : any) {
return `${value}`
}
}
}]
}
}
}
return (
<div>
<Bar
data={state}
options={opt}
/>
</div>
)
Example of the current problem

custom label title for scatter in React-ChartJS-2

I try to make a scatter plot using React-ChartJS-2. The basic setting gives only the values of the x-value and the y-value of the point in the plot. Is there any way to show the label for the point in the plot?
I lookup around and found the code seemed to work, but it did not.
const optionsScatterPlot = {
plugins: {
tooltip: {
callbacks: {
title: function (tooltipItem:any, data:any) {
const dataLabel = dataScatterPlot.labels[tooltipItem.index];
return dataLabel;
}
}
},
},
};
const Scatter = () => {
return (
<div>
<Box maxWidth="lg" margin="auto" >
AdEfficiency
</Box>
<Scatter options={optionsScatterPlot} data={dataScatterPlot} />
</div>
)
}
Add label title to either of the axes like so:
const options = {
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'label for Y'
}
},
x: {
beginAtZero: true,
title: {
display: true,
text: 'label for X'
}
},
},
};
the text property is the text label to be displayed on the axes. 'options' variable is what you pass to the options prop.

react-chartjs-2 options are not recognized for Bars

I am trying to built a barchart component via "react-chartjs-2". I did pretty much paste my code from here: https://www.c-sharpcorner.com/article/create-different-charts-in-react-using-chart-js-library/.
This is how it looks:
import React from 'react';
import {Bar} from "react-chartjs-2";
const BarChart = () => {
const barChartData = {
labels: ["October", "November", "December"],
datasets: [
{
data: [8137119, 9431691, 10266674],
label: "Infected People",
borderColor: "#3333ff",
backgroundColor: "#547db4",
fill: true
},
{
data: [1216410, 1371390, 1477380],
label: "Deaths People",
borderColor: "#ff3333",
backgroundColor: "#f7813e",
fill: true
}
]
};
const barChart = (
<Bar
type="bar"
width={130}
height={50}
options={{
title: {
display: true,
text: "COVID-19 Cases of Last 3 Months",
fontSize: 15
},
legend: {
display: true, //Is the legend shown?
position: "bottom" //Position of the legend.
}
}}
data={barChartData}
/>
);
return barChart;
};
export default BarChart
Everything seems to be working fine, besides the fact that the options prop is not being recognized by the code.
Did anyone come across a similar issue and can help me out?
Update options prop as bellow.
options = {{
plugins: {
title: {
display: true,
text: "COVID-19 Cases of Last 3 Months"
},
legend: {
display: true,
position: "bottom"
}
}
}}

Using zoom/pan with ChartJS

So I've been using react ChartJS to build some graphs, but eventually I ran into scroll problems that I couldn't solve with chartjs, so I found Apex that has Zoom built-in and I could make it scrollable.
But now since they are two completely different libs, so I can't copy it 100% the way it was.
I did not find anything on the docs talking about multiple labels in one value, so if anyone could help me with this one.
And if you see close enough there are some line running on the chart below, are those possible to do with Apex? (I'm using a customPlugin in chartJS to do it)
Ok, in the end I changed back to ChartJS and used the chartjs-plugin-zoom plugin to do the same thing I was doing with ApexChart, I'm placing my code in this answer in case that anyone faces the same problem.
React Bar Component:
import React from "react";
import { Bar, Chart } from "react-chartjs-2";
import ChartDataLabels from "chartjs-plugin-datalabels";
import Zoom from "chartjs-plugin-zoom";
const ChartBar = ({
data,
text,
noLabel,
stacked,
newPlugin,
labelPosition,
// test,
}) => {
Chart.register(Zoom);
return (
<div
className="graphics"
style={{
display: "flex",
alignItems: "center",
flexDirection: "column",
}}
>
{/* <h1>Gráficos</h1> */}
<div style={{ width: "65%", height: "350px" }}>
<Bar
data={data}
plugins={[
ChartDataLabels,
newPlugin ? newPlugin : "",
// test ? test : "",
]}
options={{
categoryPercentage: stacked ? 1.0 : 0.9,
barPercentage: 1.0,
// layout: {
// padding: {
// left: 0,
// right: 0,
// top: 60,
// bottom: 0,
// },
// },
responsive: true,
maintainAspectRatio: false,
plugins: {
zoom: {
// limits: { y: { min: "original", max: "original" } },
// pan: { enabled: true, mode: "xy", threshold: 10 },
// zoom: {
// wheel: {
// enabled: true,
// mode: "xy",
// },
// },
limits: { y: { min: "original", max: "original" } },
pan: { enabled: true, mode: "x", threshold: 10 },
zoom: {
mode: "x",
drag: {
enabled: true,
backgroundColor: "rgba(225,0,225,0.3)",
},
wheel: {
enabled: true,
modifierKey: "alt",
},
},
},
tooltip: { enabled: false },
legend: {
display: noLabel ? false : true,
position: labelPosition ? labelPosition : "bottom",
title: { padding: 40 },
},
title: { text: text, display: true, padding: 30 },
},
scales: {
// scaleLabel: { display: true },
x: {
stacked: stacked ? true : false,
// ticks: {
// display: false,
// autoSkip: true,
// maxTicksLimit: 10,
// beginAtZero: true,
// },
// gridLines: {
// display: false,
// },
},
y: { stacked: stacked ? true : false, ticks: { display: false } },
// xAxes: [{ scaleLabel: { display: true } }],
},
}}
/>
</div>
</div>
);
};
export default ChartBar;
One data object that is being used with this component(eg. the one in the main question):
{
customPlugin: {
id: "customValue",
afterDraw: (chart, args, opts) => {
const {
ctx,
data: { datasets },
_metasets,
} = chart;
datasets[1].data.forEach((dp, i) => {
let increasePercent =
(dp * 100) / datasets[0].data[i] >= 100
? Math.round(
((dp * 100) / datasets[0].data[i] - 100) * 100
) / 100
: (Math.round(
(100 - (dp * 100) / datasets[0].data[i]) * 100
) /
100) *
-1;
let barValue = `${increasePercent}%`;
const lineHeight = ctx.measureText("M").width;
const offset = opts.offset || 0;
const dash = opts.dash || [];
ctx.textAlign = "center";
ctx.fillText(
barValue,
_metasets[1].data[i].x,
_metasets[1].data[i].y - lineHeight * 1.5,
_metasets[1].data[i].width
);
if (_metasets[0].data[i].y >= _metasets[1].data[i].y) {
ctx.beginPath();
ctx.setLineDash(dash);
ctx.moveTo(_metasets[0].data[i].x, _metasets[0].data[i].y);
ctx.lineTo(
_metasets[0].data[i].x,
_metasets[1].data[i].y - offset
);
ctx.lineTo(
_metasets[1].data[i].x,
_metasets[1].data[i].y - offset
);
ctx.stroke();
} else {
ctx.beginPath();
ctx.setLineDash(dash);
ctx.moveTo(
_metasets[0].data[i].x,
_metasets[0].data[i].y - offset
);
ctx.lineTo(
_metasets[1].data[i].x,
_metasets[0].data[i].y - offset
);
ctx.lineTo(
_metasets[1].data[i].x,
_metasets[1].data[i].y - offset - lineHeight * 2
);
ctx.stroke();
}
});
},
},
text: "Evolução da Receita Líquida por Produto",
type: "bar",
// labels: values?.estimatedProducts?.map((v, i) => {
// return `Rec Líq - Prod ${++i}`;
// }),
labels: addNewArrayValue(values?.estimatedProducts, true),
datasets: [
{
type: "bar",
label: values?.monthsLabels?.mesBaseLabel,
data: values?.productsValues?.receitaLiquidaBase,
backgroundColor: ["rgba(42,62,176, 1)"],
datalabels: {
font: {
size: 10,
},
rotation: -90,
color: "white",
formatter: (value, context) => {
if (value !== 0) {
return value
?.toFixed()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// ?.toFixed(0)
// .replace(/\d(?=(\d{3})+\.)/g, "$&,");
} else {
return 0;
}
},
},
},
{
type: "bar",
label: values?.monthsLabels?.mesOrcadoLabel,
data: values?.productsValues?.receitaLiquidaOrcado,
backgroundColor: "orange",
datalabels: {
font: {
size: 10,
},
rotation: -90,
color: "black",
formatter: (value, context) => {
if (value !== 0) {
return value
?.toFixed()
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return 0;
}
},
},
},
],
},
Yeah, it's not the best code, but it's a starter, I've been struggling for 1h30m just because there's little to no actual examples/doc on this case.

Why does highcharts shrink on re-render?

I'm using highcharts-react-official to render a HighchartsReact component. It shows up and works appropriately until I re-render the component. By changing the state at all, the chart will shrink vertically.
I've experimented with setting reflow in the chart options as well as toggling allowChartUpdate and immutable flags on the component itself to no avail.
const ChartView = props => {
const { data } = props;
if(data.highstockData && data.startDate && data.endDate) {
const min = parseInt(moment(data.startDate, 'x').startOf('day').format('x'));
const max = parseInt(moment(data.endDate, 'x').startOf('day').format('x'));
const chartOptions = getChartConfig(data.highstockData, min, max);
return (
<HighchartsReact
highcharts={Highcharts}
options={chartOptions}
/>
)
}
return null;
};
And the parent Component's render return:
return (
<div className="vertical-margin">
{isFetching && !data && <LoadingView/>}
{hasError && !data && <ErrorView/>}
{
data &&
<React.Fragment>
{buttonRow}
<ChartView
data={data}
/>
</React.Fragment>
}
</div>
)
As I said re-rendering for any reason causes the highchart to shrink in height with each re-render. For testing, I call this line:
this.setState({});
I could post the chart config if needed, but it's nothing too fancy.
I haven't been able to find anyone else having this issue and have been pulling my hair out searching for an answer.
It turned out to indeed be a highchart option I was passing into the component. Apparently it was because this option:
scrollbar: {
enabled: true
},
Was not nested under the xAxis section of the options as it should be. It still created a scrollbar correctly but caused this weird, shrinking issue on component render.
chart: {
marginRight: 75,
ignoreHiddenSeries: false,
panning: false,
spacingTop: 10,
height: `${Constants.HIGHCHART_TABLE_HEIGHT}px`,
},
time: {
useUTC: false
},
credits: {
enabled: false
},
exporting: {
enabled: false
},
legend: {
align: 'left',
enabled: true,
itemMarginTop: 5,
itemStyle: {
"color": "#333333",
"cursor": "pointer",
"fontSize": "12px",
"fontWeight": "normal",
"width": "240px"
},
layout: 'vertical',
verticalAlign: 'top',
y: 0
},
navigator: {
enabled: false,
xAxis: {
tickPixelInterval: 100
}
},
plotOptions: {
line: {
marker: {
enabled: true,
fillColor: "#ffffff",
lineColor: null,
lineWidth: 1
}
}
},
rangeSelector: {
enabled: false
},
tooltip: {
formatter: function () {
const sortedPoints = this.points.sort((a, b) => {
return a.point.legendOrder - b.point.legendOrder
});
return [
'<b>',
moment(this.x, 'x').format('MM/DD/YYYY HH:mm'),
'</b><br/>',
sortedPoints.map((item) => {
return [
'<br/><span style="color:'+ item.series.color +';">\u258c</span> ',
'<span>' + item.series.name + '</span>: <b>' + item.y + '</b>',
item.comments ? '<p>(' + item.comments + ')</p>' : ''
].join('');
}).join('')
].join('');
},
shared: true,
crosshairs: {
color: '#ddd',
dashStyle: 'solid'
},
},
xAxis: {
type: 'datetime',
labels:{
formatter: function() {
const parsed = moment(this.value, 'x');
return parsed.format('HH:mm') + '<br/>' + parsed.format('MM/DD');
}
},
min,
max,
reversed: true,
scrollbar: {
enabled: true
},
},
yAxis: [{
alignTicks: false,
max: 60,
min: 0,
opposite: false,
tickInterval: 5,
title: {
text: ''
}
}, {
alignTicks: false,
max: 300,
min: 0,
opposite: true,
tickInterval: 25,
title: {
text: ''
}
}],
//The below properties are watched separately for changes.
series: data,
title: {
text: ''
},
loading: false,
};
Also here's the full options file for reference. It wasn't just that scrollbar option causing it. It was a specific combination of options as I discovered by trying to re-create the problem with a new chart.

Resources