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

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>

Related

Recharts/Reactjs - I don't know how to extend my line

I am doing a projets using Recharts for my study and I struggle with respecting the model
this is my current line chart
and I need to extend the line like this without affecting the days on the bottom/xAxis
I used padding on the xAxis but that affects the line, so it dosn't stay stick to the borders as expected.
This is my component :
function LineCharts() {
return (
<div className="bottom-cards">
<h2 id="session-time-h2">Durée moyenne des sessions</h2>
<ResponsiveContainer width="100%" aspect={1}>
<LineChart
width={500}
height={300}
data={data}
margin={{
top: 100,
right: 0,
left: 0,
bottom: 20,
}}
onMouseMove={handleMouseMove}
>
<defs>
<linearGradient
id={gradientId}
x1="0"
y1="1"
x2="0"
y2="0"
gradientTransform="rotate(270)"
>
<stop
offset="1.19%"
stopColor="#FFFFFF"
stopOpacity={1}
/>
<stop
offset="81.27%"
stopColor="rgba(255, 255, 255, 0.403191)"
stopOpacity={1}
/>
</linearGradient>
</defs>
<XAxis
dataKey="name"
tickLine={false}
axisLine={false}
stroke="white"
opacity={0.5}
interval="preserveStartEnd"
padding={{ left: 20, right: 20 }}
/>
<Tooltip />
<Line
type="natural"
dataKey="value"
stroke={gradientUrl}
dot={false}
activeDot={{ stroke: "white", strokeWidth: 2 }}
/>
<ReferenceArea x1="60" x2="80" strokeOpacity={0.3} />
</LineChart>
</ResponsiveContainer>
</div>
);
}
export default LineCharts;

How to get Recharts to dynamically change color from a variable in data

I'm trying to add color to parts of a Rechart plot (based on a value in the data). The chart that I'm trying to recreate is shown below. Here is my code currently which just plots the chart with one color https://codesandbox.io/s/stupefied-shamir-e1u0vt?file=/src/App.js.
I tried using linearGradient in the way shown below (commented) but that seems to gives 2 colors (red if above a certain y value and green if below).
The data format:
>>> data = [{X: 100, Y: 200, Speed: 0},{X: 200, Y: 200, Speed: 1},{X: 300, Y: 400, Speed: 3}]
Current Recharts Code:
<LineChart
width={600}
height={300}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
data={data}
>
{/* <defs>
<linearGradient id="colorSpeed" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stopColor="red" />
<stop offset="100%" stopColor="green" />
</linearGradient>
</defs> */}
<Line dot={false} type="monotype" dataKey="Y"
// stroke="url(#colorSpeed)"
/>
<XAxis type="number" dataKey="X" domain={["auto", "auto"]} />
<YAxis domain={("auto", "auto")} />
<Tooltip />
<Legend />
</LineChart>
What I'm trying to recreate:

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
}

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

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"
/>

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