Nikhil Ponduri
Nikhil Ponduri

Reputation: 531

Recharts grouping x-axis Labels

I have a requirement where I need to show the values between 1,2 as a group and 2,3 as a seperate group. I am trying to customise the x-axis but it's not workingenter image description here

In the above picture I need to show the bars 3 and 3.5 together with miminum gap between them and in sameway 4 and 4.5 together

and this is my code

 <ResponsiveContainer width="100%" height="100%">
        <ComposedChart
          width={500}
          height={400}
          data={data}
        >
          <CartesianGrid horizontal={false} strokeDasharray="4 4" />
          <XAxis scale="point" dataKey="label" />
          <YAxis label={{ value: 'No.Of Employees', angle: -90, position: 'insideLeft' }} tick={false} />
          <Tooltip />
          <Bar dataKey="count" barSize={40} fill="#AAE5F9" />
          <Line connectNulls={true} strokeWidth={3} dot={false} type="monotone" dataKey="count" stroke="#3080ED" />
          
        </ComposedChart>
      </ResponsiveContainer>

Any help would be thankfull

Upvotes: 2

Views: 7762

Answers (1)

Wild Zyzop
Wild Zyzop

Reputation: 620

I assume your data looks like this:

const data = [
  {label: "0", count: 0},
  {label: "1", count: null},
  {label: "2", count: 1},
  {label: "3", count: 1},
  {label: "3.5", count: 1},
  {label: "4", count: 2},
  {label: "4.5", count: 1},
  {label: "5", count: 0},
];

They must be converted to the following form:

const data = [
  {label: "0", countA: 0, countB: null},
  {label: "1", countA: null, countB: null},
  {label: "2", countA: 1, countB: null},
  {label: "3-3.5", countA: 1, countB: 1},
  {label: "4-4.5", countA: 2, countB: 1},
  {label: "5", countA: 0, countB: 0},
];

The first method

Add another Bar component to display values in group.

export default function App() {
  return (
    // <ResponsiveContainer width="100%" height="100%">
      <ComposedChart
          width={500}
          height={400}
          data={data}
        >
          <CartesianGrid horizontal={false} strokeDasharray="4 4" />
          <XAxis scale="point" dataKey="label" />
          <YAxis label={{ value: 'No.Of Employees', angle: -90, position: 'insideLeft' }} tick={false} />
          <Tooltip />
          <Bar dataKey="countA" barSize={20} fill="#AAE5F9" />
          <Bar dataKey="countB" barSize={20} fill="#79B473" />
          <Line connectNulls={true} strokeWidth={3} dot={false} type="monotone" dataKey="countA" stroke="#3080ED" />
        </ComposedChart>
        // </ResponsiveContainer>  
        );
}

Result:

result

The second method

If you want the columns in the groups to be the same width regardless of how many elements are in the group, then you can draw the rectangle for the group yourself.

const getPath = (x, y, width, height, uv, pv) => {
  const height1= pv?(height/uv)*pv:height;
  return `M${x},${y}
  v${height} 
  h${width}
  v${-height1} 
  h${-width/2}
  v${(height1-height)} 
  h${-width/2}
  Z`;
};

const MultiBar: FunctionComponent = (props) => {
  const { fill, x, y, width, height, countA, countB } = props;
  return <path d={getPath(x, y, width, height, countA, countB)} stroke="none" fill={fill} />;
};

export default function App() {
  return (
    <ComposedChart
      width={500}
      height={400}
      data={data}
    >
      <CartesianGrid horizontal={false} strokeDasharray="4 4" />
      <XAxis dataKey="label" />
      <YAxis type="number" domain={[0, 2]} label={{ value: 'No.Of Employees', angle: -90, position: 'insideLeft' }} tick={false} />
      <Bar
        dataKey="countA"
        fill="#AAE5F9"
        shape={<MultiBar />}
      >
      </Bar>
      <Line connectNulls={true} strokeWidth={3} dot={false} type="monotone" dataKey="countA" stroke="#3080ED" />
    </ComposedChart>
  );
}

Result:

enter image description here

The getPath function returns the path of the SVG element for drawing each bar of the chart. If required, you can add a stroke or make a gap between the bars in the group.

Also, you need to set the domain for the Y-axis by the maximum value of all countA and countB values:

<YAxis type="number" domain={[0, 2]} ... />

Upvotes: 1

Related Questions