Recharts - Horizontally Align Line and Bar Charts - javascript

I am using Recharts and have a component that displays a line chart followed by a bar chart. The two charts are displaying the same seven day span, but the ticks are not aligned. The line chart starts on the Y Axis line, while the bar chart has left padding (by default).
On the line chart I tried adding padding={{left: 100 }}, which got the starting of the X axes aligned, but the rest of the ticks were off, and more importantly it isn't responsive to the screen size. As far as I can tell using something like '5%' is not allowed.
On the bar chart I tried setting the padding to zero and a negative number, but ran into the same issues with responsive scaling and tick misalignment.
Is there a way to align the ticks and data on the two graphs?
Here is the code:
<ResponsiveContainer width="95%" height={300} >
<LineChart width={350} height={300} data={this.props.data.activityResponse.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Line type="monotone" dataKey="node.participation" stroke={this.participationColor} name="Participation" strokeWidth={this.strokeWidth} />
<Line type="monotone" dataKey="node.focus" stroke={this.focusColor} name="Focus" strokeWidth={this.strokeWidth} />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.participation" >
<Label value="%" position="insideLeft" />
</YAxis>
<Tooltip content={this.renderResponseTooltip} />
</LineChart>
</ResponsiveContainer>
<ResponsiveContainer width="95%" height={300} >
<BarChart width={350} height={300} data={this.props.data.activityStep.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Bar dataKey="node.stepCount" fill={this.stepColor} name="Steps" />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.stepCount" >
</YAxis>
<Tooltip content={this.renderStepTooltip} />
</BarChart>
</ResponsiveContainer>

I'm not sure if you are still interested in this, since the question is pretty old, but I have found a solution that worked for me.
You can use ComposedChart to solve this. Taking your code, the solution should look something like this:
<ResponsiveContainer width="95%" height={300} >
<ComposedChart data={this.props.data.activityResponse.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Line type="monotone" dataKey="node.participation" stroke={this.participationColor} name="Participation" strokeWidth={this.strokeWidth} />
<Line type="monotone" dataKey="node.focus" stroke={this.focusColor} name="Focus" strokeWidth={this.strokeWidth} />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.participation" >
<Label value="%" position="insideLeft" />
</YAxis>
<Tooltip content={this.renderResponseTooltip} />
</ComposedChart>
</ResponsiveContainer>
<ResponsiveContainer width="95%" height={300} >
<ComposedChart data={this.props.data.activityStep.edges} connectNulls={true} >
<Legend verticalAlign="top" height={36}/>
<Bar dataKey="node.stepCount" fill={this.stepColor} name="Steps" />
<XAxis dataKey="node.logDate" tickFormatter={this.formatXAxis} />
<YAxis dataKey="node.stepCount" >
</YAxis>
<Tooltip content={this.renderStepTooltip} />
</ComposedChart>
</ResponsiveContainer>
I also removed your width / height arguments on the charts since the ResponsiveContainer will take care of that already.
In my personal case, this solves the issue, when I try to horizontally align an Area and a Bar Chart.
Providing a syncid for both charts, by adding that attribute to both ComposedCharts, the Tooltip will also follow in both charts simultaneously.

This link might help in this case.
Try syncId="anyId" on both LineChar and BarChar element.
Rechart - SynchronizedLineChart

Related

Recharts Stacked bar chart hides bar with less value

When trying to show multiple bar charts stacked horizontally the bar with large points covers up the maximum space and the bar with less points is overlapped, How to show fix this or add minimum with to each bar as in case of value one it shows the bar clearly.
<ResponsiveContainer height={50} width={"100%"}>
<BarChart
layout="vertical"
data={[bar]}
margin={{left: 30, right: 50}}
stackOffset="expand"
>
<XAxis hide type="number"/>
<YAxis
type="category"
dataKey="name"
fontSize="20"
hide
/>
<Tooltip wrapperStyle={{zIndex: 1}} cursor={{fill: 'transparent'}}/>
{bar['Not Triggered'] && <Bar dataKey="Not Triggered" fill="#FF6D6F" stackId="a" isAnimationActive={false}>
<LabelList
dataKey='Not Triggered'
position="center"
content={renderBarCustomizedLabel}
/>
</Bar>}
{bar['Not Started'] && <Bar dataKey="Not Started" fill="#F9AB4B" stackId="a" isAnimationActive={false}>
<LabelList
dataKey="Not Started"
position="center"
content={renderBarCustomizedLabel}
/>
</Bar>}
{bar['Ongoing'] && <Bar dataKey="Ongoing" fill="#57B0E2" stackId="a" isAnimationActive={false}>
<LabelList
dataKey="Ongoing"
position="center"
content={renderBarCustomizedLabel}
/>
</Bar>}
{bar['completed'] && <Bar dataKey="Completed" fill="#4EA167" stackId="a" isAnimationActive={false}>
<LabelList
dataKey="Completed"
position="center"
content={renderBarCustomizedLabel}
/>
</Bar>}
</BarChart>
</ResponsiveContainer>

How to position all dates on xAxis using recharts and stretch width on 100% in React?

1. I want to position on xAxis all dates (5 days every 3 hours) vertically ?
2. I want to stretch the graphic with a width of 100% on the screen and a height of 600 px ?
<LineChart width={600} height={200} data={chartData}>
<Line type="monotone" dataKey="temp" stroke="#fc7f03" name="Temperature" unit=" °C"/>
<CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
<XAxis dataKey="date" tick={{fontSize: 10, fill: 'orange'}} tickFormatter={(unixTime) => moment(unixTime).format('DD.MM - HHч.')}/>
<YAxis />
<Tooltip />
</LineChart>
Examples on recharts
If you check their example you will find that they have a component
https://recharts.org/en-US/api/ResponsiveContainer
ResponsiveContainer
You can import it from
"recharts"
and then use it like in their example
<ResponsiveContainer width="100%" height="100%">
<LineChart
width={500}
height={300}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5,
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="pv" stroke="#8884d8" activeDot={{ r: 8 }} />
<Line type="monotone" dataKey="uv" stroke="#82ca9d" />
</LineChart>
</ResponsiveContainer>
Also you can set settings for your XAxis.
Check docs here https://recharts.org/en-US/api/XAxis#tickCount

Position a foreignObject to the top-right of an svg

I'm adding a foreignObject to a chart built upon svg. I want to put it on the top-right of the svg, irrespective of how big/small that svg is. So I don't want a hardcoded solution, I need a dynamic solution.
Setting width={'100%'} height={'100%'} inside the foreignObject isn't workable, because it makes the rest of the chart unclickable.
I've got a non-dynamic solution by setting x and y manually inside foreignObject, but I need a dynamic solution.
How can I achieve this?
<g>
<foreignObject //x={0} y={0}
width={'1'} height={'1'} style={{overflow: 'visible'}} x={50} y={50}>
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}
transition="all 0.001s"
borderRadius="md"
borderWidth="0px"
_hover={{ bg: "gray.400" }}
_expanded={{ bg: "blue.400" }}
_focus={{ boxShadow: "none" }}
style={{ marginTop: "1px", position: "absolute", right: 0 }}>
Actions
</MenuButton>
<Portal>
<MenuList zIndex={10}>
<MenuItem>Download</MenuItem>
<MenuItem>Create a Copy</MenuItem>
<MenuItem>Mark as Draft</MenuItem>
<MenuItem>Delete</MenuItem>
<MenuItem>Attend a Workshop</MenuItem>
</MenuList>
</Portal>
</Menu>
</foreignObject>
</g>
Codesandbox:
https://codesandbox.io/s/floral-water-v11gx?file=/src/BasicLineSeries.tsx
Your parent component BasicLineSeries already knows the width, so you can pass that into the component generating the foreignObject as follows:
<ChartCanvas
height={height}
ratio={ratio}
width={width}
...
>
<Chart id={1} yExtents={this.yExtents}>
<LineSeries yAccessor={this.yAccessor} strokeWidth={3} />
<XAxis />
<YAxis />
</Chart>
<TestMenu width={width} />
</ChartCanvas>
function TestMenu({width}) {
return (
<g className="react-financial-charts-enable-interaction">
<foreignObject
width={"1"}
height={"1"}
style={{ overflow: "visible" }}
x={width}
y={50}
>

Recharts - align axis label in the left side

I am creating a horizontal bar graph using recharts library. I want to align the y-axis label in the left side.
<BarChart width={400} height={300} data={data} layout="vertical" margin={{right: 40}}>
<XAxis hide axisLine={false} type="number"/>
<YAxis dataKey="name" type="category" axisLine={false} tickLine={false} />
<Bar dataKey="pv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#8884d8" background={{fill: "#eee", radius: [20,20,20,20]}} tick={false} />
<Bar dataKey="uv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#eee" >
<LabelList dataKey="amt" position="right" />
</Bar>
</BarChart>
Jsfiddle
You can accomplish this by using a custom Tick component.
const CustomYAxisTick = React.createClass({
render() {
const { x, y, payload } = this.props;
return (<g transform={`translate(${0},${y})`}>
<text x={0} y={0}
textAnchor="start"
fill="#666">{payload.value}</text>
</g>)
}
})
And then you can use that in your YAxis:
<YAxis tick={<CustomYAxisTick />} />
I forked your JSFiddle and added those changes.

ReCharts - not able to see label when right aligned for stacked bar chart

I am creating an example of StackBarChart using Recharts library but I am not able to see the label when it's position is set to "right" though I am able to show the other label positions.
<BarChart width={400} height={300} data={data} layout="vertical">
...
<Bar dataKey="pv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#8884d8" background={{fill: "#ddd", radius: [20,20,20,20]}} tick={false} />
<Bar dataKey="uv" stackId="a" barSize={15} radius={[20,20,20,20]} fill="#aaa" >
<LabelList dataKey="name" position="right" />
{/* works fine <LabelList dataKey="name" position="top" /> */}
</Bar>
</BarChart>
Here is the Jsfiddle(updated).
I have updated your fiddle script here.
You have to provide a correct dataKey field to LabelList, and put LabelList as a child of Bar component
UPDATED:
New jsfiddle, you need margin in your case. So that the SVG reserved some spaces aside of the chart for additional text. NOTE that it is the margin props of the chart, not the margin from CSS style.

Categories

Resources