chartjs-plugin-zoom: get currently visible values when the page first loads - reactjs

I have a chart component called genStarts whose view depends on the visible data of the following chart (singleChart). I'm using the onZoomComplete and onPanComplete options to insert my getVisibleValues function so that genStarts can be updated on zooms and pans. However, I have no way to get the currently visible values when the page first starts up. My getVisibleValues function does not work outside of the chartStyle object, and I haven't found a chart option that executes on startup.
In other words, my genStarts graph is only populated when SingleChart is zoomed or panned but I want it to be populated immediately.
const SingleChart = React.memo(({ setVisible }) => {
function getVisibleValues({ chart }) {
setVisible(chart.scales.x.ticks);
}
const chartStyle = {
options: {
animation: false,
maintainAspectRatio: false,
responsive: true,
plugins: {
zoom: {
zoom: {
wheel: {
enabled: true,
modifierKey: "shift",
},
pinch: {
enabled: true,
},
enabled: true,
drag: true,
mode: "x",
onZoomComplete: getVisibleValues,
},
pan: {
enabled: true,
mode: "x",
speed: 2,
onPanComplete: getVisibleValues,
},
mode: "xy",
},
legend: {
display: false,
},
},
scales: {
y: {
type: "linear",
display: "true",
position: "left",
grid: {
drawBorder: true,
color: "#000000",
},
ticks: {
beginAtZero: true,
color: "#000000",
},
title: {
display: yAxisLabel != "",
text: yAxisLabel,
},
},
x: {
max: 9,
grid: {
drawBorder: true,
color: "#00000",
},
ticks: {
beginAtZero: false,
color: "#000000",
},
},
},
},
};
// ... some code to get chartData
return (
<div>
<Line
data={chartData}
options={chartStyle.options}
width={20}
height={195}
/>
</div>
);
});
export default SingleChart;

You can make use of the animations, they have a property to check if its the first time they have fired, although since you dont want animations you will need to set the main one to a verry low number and at least the tooltip to false and the transition duration of active elements to 0.
const getVisibleValues = ({
chart
}) => {
console.log(chart.scales.x.ticks.map(el => ({
value: el.value,
label: el.label
}))) // Map because stack console prints whole circular context which takes long time
}
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
}]
},
options: {
animation: {
onComplete: (ani) => {
if (ani.initial) {
getVisibleValues(ani)
}
},
duration: 0.0001
},
transitions: {
active: {
animation: {
duration: 0
}
}
},
plugins: {
tooltip: {
animation: false
}
}
}
}
const 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/3.5.0/chart.js"></script>
</body>

Related

change chart canvas size move mouse point over the chart using chart.js

I create some chart in dashboard using react-chart-js.
exmaple
but I have problem now chart not clear. I decided do change chart canvas size move mouse point over the chart . but i can't find solution for that.
i currently use "react-chartjs-2": "3.3.0" and "chart.js": "^3.6.0" packages
i use this option list for draw charts
const options = {
responsive: true,
animation: {
duration: 0,
},
plugins: {
legend: {
fullSize: false,
position: "bottom" as const,
labels: {
display: true,
},
},
title: {
display: true,
color: "white",
font: {
size: 14,
family: "tahoma",
weight: "normal",
style: "italic",
},
text: axis.thresholdValues.sensorName,
},
subtitle: {
display: true,
text: `average: x-axis: ${axis.average.x} y-axis: ${axis.average.y} z-axis: ${axis.average.z}`,
color: "white",
align: "end",
font: {
size: 12,
family: "tahoma",
weight: "normal",
style: "italic",
},
// padding: {
// bottom: 20,
// },
},
zoom: {
pan: {
// pan options and/or events
enabled: true,
speed: 0.01,
},
limits: {
// axis limits
},
zoom: {
// zoom options and/or events
wheel: {
enabled: true,
},
pinch: {
enabled: true,
},
speed: 0.01,
},
},
annotation: {
annotations: {
min: {
// type: 'line',
yMin: axis.thresholdValues.min,
yMax: axis.thresholdValues.min,
borderColor: "#D8D8D8",
// borderWidth: 2,
},
max: {
// type: 'line',
yMin: axis.thresholdValues.max,
yMax: axis.thresholdValues.max,
borderColor: "#DB00FF",
// borderWidth: 2,
},
},
},
tooltip: {
mode: "index",
intersect: false,
},
},
spanGaps: true,
datasets: {
line: {
pointRadius: 0, // disable for all `'line'` datasets
},
},
elements: {
point: {
radius: 0, // default to disabled in all datasets
},
},
transitions: {
zoom: {
animation: {
duration: 0,
},
},
},
scales: {
x: {
title: { display: true, text: "Time", align: "end" },
type: "time",
},
y: {
title: { display: true, text: "second", align: "top" },
},
},
events: ["click"],
hover: {
mode: "nearest",
intersect: false,
},
};
<Line data = {data} option = {option} />
Any one can suggest solution for it.

Using chartjs to limit data?

I have a react chartjs project that uses chartjs-chart-matrix to render a heatmap. My code config looks like so:
const getHeatmapConfig = ({
heatmapData,
getBackgroundColor,
xAxisLabels,
tissues: items,
openMenu,
title
}) => ({
type: 'matrix',
data: {
datasets: [
{
data: heatmapData,
backgroundColor: function (ctx) {
const value = ctx.dataset.data[ctx.dataIndex].v;
return getBackgroundColor(colors, value);
},
}
]
},
options: {
scales: {
x: {
type: 'category',
labels: xAxisLabels,
offset: true,
position: 'bottom',
stacked: true,
ticks: {
autoSkip: true,
maxRotation: 90,
minRotation: 90
},
grid: {
display: false,
drawBorder: false
}
},
y: {
type: 'category',
labels: items,
reverse: false,
offset: true,
grid: {
display: false,
drawBorder: false
},
ticks: {
autoSkip: true
}
}
},
plugins: {
legend: false,
title: {
align: 'center',
font: { size: 15 },
display: true,
text: title
},
tooltip: {
callbacks: {
title() {
return '';
},
}
}
}
}
});
My question is - I want to ensure that their are never more than 50 values and labels on the x axis but there doesn't seem to be a straightforward way of limiting the data like this. Is it possible?
You should limit the array of labels that you pass into your component.
For example: xAxisLabels.slice(0, 50)

Title is undefined in react-chart

I am building a covid-19 tracker, but when data is displayed on the graph using react charts title is coming out to be undefined
This is my chart code
<div >
{data?.length > 0 && (
<Line
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data,
},
],
}}
options={options}
/>
)}
</div>
These are my option parameters
const options = {
legend: {
display: false,
},
elements: {
point: {
radius: 0,
},
},
maintainAspectRatio: false,
tooltips: {
mode: "index",
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return numeral(tooltipItem.value).format("+0,0");
},
},
},
scales: {
xAxes: [
{
type: "time",
time: {
format: "MM/DD/YY",
tooltipFormat: "ll",
},
},
],
yAxes: [
{
gridLines: {
display: false,
},
ticks: {
// Include a dollar sign in the ticks
callback: function (value, index, values) {
return numeral(value).format("0a");
},
},
},
],
},
};
Although legend is set to false I am getting an error.
Please tell me where I am going wrong, that will be helpful.
Image of a chart.
You need to pass the label property here
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data,
label: "your label" // <-- pass this
},
],
}}

ApexCharts Remove extra bottom padding

I have the following bar chart configuration.
const series = [
{
name: 'Net Profit',
data: [18, 34, 55, 57, 80, 70],
},
];
const options = {
chart: {
type: 'bar',
height: '50px',
toolbar: {
show: false,
},
},
grid: {
show: false,
padding: {
top: 0,
bottom: 0,
},
xaxis: {
lines: {
show: false,
},
},
yaxis: {
lines: {
show: false,
},
},
},
plotOptions: {
bar: {
horizontal: false,
columnWidth: '80%',
barHeight: '100%',
},
},
dataLabels: {
enabled: false,
},
stroke: {
show: false,
width: 0,
colors: ['transparent'],
},
fill: {
opacity: 1,
colors: [
'#000000',
'#B32824',
'#1A73E8',
'#B32824',
'#1A73E8',
'#B32824',
],
type: 'solid',
},
tooltip: {
enabled: false,
},
xaxis: {
axisTicks: {
show: false,
},
axisBorder: {
show: false,
},
labels: {
show: false,
},
},
yaxis: {
axisTicks: {
show: false,
},
axisBorder: {
show: false,
},
labels: {
show: false,
},
},
};
I am getting extra padding at the bottom as below. how can I remove that?
If you don't want to show x-axis and y-axis in your chart, you can simply do
const options = {
chart: {
type: 'bar',
height: '250px',
sparkline: {
enabled: true
}
},
}
The sparkline option will remove all paddings/margins around the chart.
I was facing the same issue, and after reading the doc I found that you should set the value of parentHeightOffset as 0, something like this
var opt1 = {
chart: {
type: 'line',
height: 200,
...
parentHeightOffset: 0,
...
},
...
};

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