Recharts - How to force chart to start at x=0? - reactjs

I'm using Recharts to draw some charts. Depending on the length of the data array, the chart doesn't start at x = 0 (not at the intersection of x and y) and doesn't finish at the max value of x:
How can I force it to always begin at x = 0 and occupy all the x axis?
This is how I'm implementing it:
<ResponsiveContainer width="100%" height={400}>
<ComposedChart
data={chartContent.content.chart}
//data={data}
margin={{ top: 5, bottom: 5, left: 5 }}
>
<defs>
<linearGradient
id="colorBtc"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor="#ff9500"
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor="#ff9500"
stopOpacity={0}
/>
</linearGradient>
<linearGradient
id="colorStock"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor="#00a1e4"
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor="#00a1e4"
stopOpacity={0}
/>
</linearGradient>
</defs>
<XAxis
dataKey="date"
tickFormatter={formatDate}
/>
<YAxis tickFormatter={formatYAxis} />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip
formatter={formatTooltip}
labelFormatter={formatDate}
/>
<Legend />
<Area
name={t("Total amount in BTC")}
type="monotone"
dataKey="investment_total_btc"
stroke="#ff9500"
fillOpacity={1}
fill="url(#colorBtc)"
/>
<Area
name={`${t("Total amount in")} ${
chartContent.content.symbol
}`}
type="monotone"
dataKey="investment_total_stock"
stroke="#00a1e4"
fillOpacity={1}
fill="url(#colorStock)"
/>
<Line
name={t("Total invested in $")}
dataKey="invested"
type="monotone"
stroke="#ff0000"
dot={false}
/>
</ComposedChart>
</ResponsiveContainer>
Unfortunately the API documentation is not so clear and I couldn't find a solution.
Thanks in advance

What helped in my scenario was to add dataMax + 1 to the domain parameter of the XAxis component.
Based on what the documentation says I would have assumed that adding 'dataMin' for the first element of the domain array would help. However, it was dataMax + 1 that resolved it for me
Full snippet
<XAxis
dataKey="date"
name="Time"
type="number"
domain={["dataMin", "dataMax + 1"]}
tickFormatter={(tickItem) => moment(tickItem).format("MMM Do YY")}
/>

Adding domain={["dataMin", "dataMax + 1"]} doesn't work, since the XAxis type in my case is category(the default value).
According to the library API document, in order to set domain, the XAxis type should be "number"reference
For category type XAxis, I found that Priyank Kachhela pointed out an alternative solution. You can specify the scale of XAxis to be point( the default scale is band ). It resolved my issue.
<XAxis
dataKey="date"
tickFormatter={formatDate}
scale="point"
/>

Related

React Recharts, difference between chromium and firefox

I have a stacked area chart with a time series. I'm normalizing the data to always add up to 100%.
With some specific data, the chart breaks, and used to break in the same way in firefox until I added scale="time" to XAxis.
Right now this is what I have:
<AreaChart data={percentData.sort((a, b) => a.name >= b.name)}>
<defs>
{colors.map((c, i) => (
<linearGradient id={`graphColor${i}`} x1="0" y1="0" x2="0" y2="1" key={c}>
<stop offset="5%" stopColor={c} stopOpacity={1} />
<stop offset="95%" stopColor={c} stopOpacity={0.5} />
</linearGradient>
))}
{customGradients()}
</defs>
<XAxis
dataKey="name"
type="number"
domain={[MIN, MAX]}
scale="time"
tickFormatter={dateFormatter}
ticks={tickArray}
tickCount={5}
>
<Label value="Date" position="bottom" style={{ textAnchor: 'middle' }} />
</XAxis>
<YAxis ticks={[0, 25, 50, 75, 100]} domain={[0, 100]} unit="%" type="number">
<Label angle={-90} value="Percentage" position="insideLeft" style={{ textAnchor: 'middle' }} />
</YAxis>
<Tooltip content={<CustomTooltip tickFormatter={dateFormatter} />} />
<CartesianGrid strokeDasharray="3 3" />
{tab
&& tab.keys
.sort()
.map((k, i) => (
<Area
type="monotone"
dataKey={k}
stroke={tab.data[`${k}color`] || getColorForCurrentIndex(i)}
fillOpacity={1}
fill={
tab.data[`${k}color`]
? `url(#graphColor${k}color)`
: `url(#graphColor${getColorIndex(i)})`
}
key={k}
stackId="1"
/>
))}
</AreaChart>
The console in chromium outputs the following:
Error: <rect> attribute x: Expected length, "NaN".
Error: <rect> attribute width: Expected length, "NaN".
I'm using unix timestamps for the x coordinates, they are proper number instances.
And this is the result in firefox:
Firefox stacked time series area chart
The first render on chromium:
Chromium stacked time series area chart first render
After re-render on chromium:
Chromium stacked time series area chart second render
Any help is appreciated, struggling with figuring this out. Thanks!
I've tried the example for Percent area chart provided in recharts docs, same result.
Turns out I wasn't sorting my data properly, even though they were numbers passed to a numeric axis, sorting the data array fixed this issue:
sort((a, b) => a.name >= b.name) => sort((a, b) => a.name - b.name)

How to plot events based on beginning and end of day in rechart

Hello I want to plot a graph on rechart library based on the data I have however I want it to be such that on the start of the x axis it labelled 12am (start of date) and end it is 11:59pm then using this I can plot a graph based on the events of the day
here is how my data looks like
const data=[{moneyIn: 100, time: '9:07 AM'}
{moneyIn: 140, time: '9:07 AM'}
{moneyIn: 250, time: '9:08 AM'}]
here is how I have plotted my current graph
<ResponsiveContainer width="99%" aspect={aspect}>
<AreaChart
width={730}
height={300}
data={data}
style
margin={{ top: 10, right: 0, left: 0, bottom: 0 }}
>
<defs>
<linearGradient id="total" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor={color} stopOpacity={0.8} />
<stop offset="95%" stopColor={color} stopOpacity={0.3} />
</linearGradient>
</defs>
<XAxis dataKey={time} stroke="gray" />
<YAxis />
<CartesianGrid strokeDasharray="3 3" className="chartGrid" />
<Tooltip />
<Area
type="monotone"
dataKey={moneyIn}
stroke={color}
fillOpacity={1}
fill="url(#total)"
/>
</AreaChart>
<ResponsiveContainer/>
this produces the folowing result
However i want the time to begin from 12am to 11:59pm then plot those points according to time, how do i do it? What other library can these be achieved in?
You can set the axes to a given value by providing the ticks attribute:
This thread on the Recharts Git discusses how.
<XAxis ticks={[1.2, 2.8, 4.4, 6]} />
You may want to have a few more ticks in your example, like 12-noon.
But you may have to format your x-axis values into a number or date value in order to make it work how you expect.
The XAxis Docs from Recharts give some good pointers on how certain props change the behaviour of the XAxis.

How to Display Ticks and Labels for Month Numbers for 4 years in the X-Axis using Recharts

I am looking for a way to display month numbers in such a way as seen below for a line chart using Recharts library:
As you can see, the chart starts with the first month of each year for 4 years of total data in the x-axis and the month increments by 2 for each year. Each year has a reference line, with the thicker stroke referenceline being the current year and month followed by future months including the next year first month as displayed.
How can I display the ticks on the x-axis along with the month numbers for each year which is denoted with the reference lines (except the beginning of the line chart should not have a reference line)? I am new to react and also to recharts so bear with me. Below is the code I have so far in the recharts components which only takes into account the year at the reference lines as a placeholder:
<ResponsiveContainer height="500px" width="99%" aspect={4}>
<LineChart
width={500}
height={300}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5
}}
>
<CartesianGrid
vertical={false}
opacity="0.4"
/>
<XAxis
dataKey="name"
tickSize={4}
/>
<YAxis
type="number"
domain={[0, 20000]}
/>
<Tooltip
content={CustomTooltip}
/>
{on1 &&
<Line type="monotone"
dataKey="cv"
stroke="#BE1710"
strokeWidth={2}
isAnimationActive={false}
dot={{r:0}}
/>
}
{on2 &&
<Line type="monotone"
dataKey="uv"
stroke="#22766F"
strokeWidth={2}
isAnimationActive={false}
dot={{r:0}}
/>
}
{on3 &&
<Line type="monotone"
dataKey="pv"
stroke="#0E65BC"
strokeWidth={2}
isAnimationActive={false}
dot={{r:0}}
/>
}
<ReferenceLine
x="2021"
stroke="black"
strokeWidth={1}
/>
<ReferenceLine x="2020" strokeWidth={0.5}/>
<ReferenceLine x="2019" strokeWidth={0.5}/>
<ReferenceLine x="2018" strokeWidth={0.5} />
</LineChart>
</ResponsiveContainer>
It seems to me that you want a ReferenceLine every 12 months (or ticks), rather than a ReferenceLine on a specific year.
Assuming that your data array has one value per month of each year, you could have your LineChart this way:
export default function App() {
return (
<ResponsiveContainer height="500px" width="99%" aspect={4}>
<LineChart
width={1000}
height={500}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5
}}
>
<CartesianGrid vertical={false} opacity="0.4" />
<XAxis
dataKey="month"
domain={[0, "dataMax"]}
tickSize={4}
interval={1}
/>
<YAxis type="number" domain={[0, 20000]} />
<Line
type="monotone"
dataKey="cv"
stroke="#BE1710"
strokeWidth={2}
isAnimationActive={false}
dot={{ r: 0 }}
/>
<Line
type="monotone"
dataKey="uv"
stroke="#22766F"
strokeWidth={2}
isAnimationActive={false}
dot={{ r: 0 }}
/>
<Line
type="monotone"
dataKey="pv"
stroke="#0E65BC"
strokeWidth={2}
isAnimationActive={false}
dot={{ r: 0 }}
/>
<ReferenceLine x="0" strokeWidth={0.5} />
<ReferenceLine x="12" strokeWidth={0.5} />
<ReferenceLine x="24" stroke="black" strokeWidth={1} />
<ReferenceLine x="36" strokeWidth={0.5} />
</LineChart>
</ResponsiveContainer>
);
}
Here, the ReferenceLine x's value is hardcoded, where the value given is associated to the first month (1) of the year.
I did that assuming that your data array contained elements such as the following:
{
month: 9,
year: 2020,
uv: 3490,
pv: 4300,
cv: 2100
}

How to align two Y-axis around 0 in React Recharts?

I have an areachart with two areas and two Y-Axis. The first area goes from -1500 to 4500. The second goes from 0 to 100. Both areas start from the bottom so the 0 value of the second one is aligned with the -1500 value of the first one. Is it possible to align the two y-axis ?
<AreaChart width={730} height={250} data={data}
margin={{ top: 10, right: 30, left: 0, bottom: 0 }}>
<defs>
<linearGradient id="colorA" x1="0" y1="0" x2="0" y2="1">
<stop offset="{off}" stopColor="green" stopOpacity={1}/>
<stop offset="{off}" stopColor="red" stopOpacity={1}/>
</linearGradient>
</defs>
<XAxis dataKey="date" />
<YAxis yAxisId="left" dataKey="number" />
<YAxis yAxisId="right" orientation="right" dataKey="percentage" domain={[0,100]} unit="%" />
<Area yAxisId="left" dataKey="number" stroke="#8884d8" fill="url(#colorA)" />
<Area yAxisId="right" dataKey="percentage" stroke="#82ca9d" fill="#eee" />
</AreaChart>

Recharts: Setting X-Axis Label Margin

How can I set the margin between X-Axis and the label (in my case 'dd.mm.yy' ?
That is my AreaChart:
<AreaChart
width={600}
height={400}
data={data}
connectNulls={true}
margin={{top: 20, left: 120, bottom: 20}}>
<defs>
<linearGradient id="colorUv" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#2198F3" stopOpacity={1}/>
<stop offset="95%" stopColor="#4BABF4" stopOpacity={0.6}/>
</linearGradient>
</defs>
<Area
dot={{ stroke: '#2196f3', strokeWidth: 4, r: 7, fill: 'white'}}
type='monotone'
dataKey='value'
stroke='#2196f3'
strokeWidth='4'
fill='url(#colorUv)'
/>
<XAxis dataKey="name" />
<YAxis orientation="right" />
<CartesianGrid strokeDasharray="3 3"/>
<Tooltip/>
</AreaChart>
p.s. recharts-tag is not available!
Try using dx and dy properties on XAxid and YAxis like this:
<XAxis dataKey="name" dy={10}/>
or
<YAxis orientation="right" dx={5}/>
Based on these values, when the SVG is rendered and the positions of the ticks are calculated, the amount that you set for dx will be added to the normal amount of the X position of the tick item. So in the case of YAxis this will add a value of 10 the the x value of the text element that represents the tick. Same goes for dy
From the docs, the default offset for a label is 5. You need to set it to 0 or less for it to not overlap ticks.

Resources