VictoryLegend: how to relatively position (e.g. bottom center)
Asked Answered
M

2

8

I'm using VictoryCharts, specifically the VictoryLegend component to render the legend for my chart. According to the docs it sounds like the only options for positioning the legend are absolute x and y coordinates. I'm trying to position the legend relatively, for example "at the bottom in the middle". This is the desired appearance:

legend centered at the bottom of the chart

Because the series labels in my legend are internationalized, the number of characters and thus the legend's width changes based on locale, so it isn't an option to hard-code an x coordinate to center the legend. I would also prefer not to have to calculate the y coordinate based on the height of my chart. Is there any way to relatively position the VictoryLegend below the chart and horizontally centered?

Momentarily answered 25/3, 2018 at 1:14 Comment(0)
M
8

According to the maintainer in a Gitter conversation, it appears this is not possible:

enter image description here

Momentarily answered 26/3, 2018 at 14:28 Comment(1)
2022, can't center a legend on the bottom of the chart 🤦‍♂️Orangeman
O
0

This is possible, but there's nothing entirely built-in with Victory charts to do it. The library has an amazing amount of flexibility but a terrible dearth of sensible defaults.

To begin, you first have to backfill basic chart responsiveness as outlined here:

https://github.com/FormidableLabs/victory/issues/396#issuecomment-773791721

Then you can use the same boundingRect width/height to position the legend as well:

https://codesandbox.io/s/loving-fog-f3ed9d?file=/index.js

Or the relevant code pieces here:

const Chart = () => {
  //NOTE victory charts don't automatically resize width 🤦‍♂️ yet - https://github.com/FormidableLabs/victory/issues/396
  const [boundingRect, setBoundingRect] = useState({ width: 0, height: 0 });
  const containerRef = useCallback((node) => {
    if (node !== null) {
      setBoundingRect(node.getBoundingClientRect());
    }
  }, []);

  //...

  return (
    <div ref={containerRef} style={{ width: "90vw", height: "90vh" }}>
      <VictoryChart
        domainPadding={30}
        theme={VictoryTheme.material}
        height={boundingRect.width * 0.9}
        width={boundingRect.width}
      >
        <VictoryBar
          data={chartData}
          cornerRadius={2}
          style={{ data: { fill: ({ datum }) => datum.fill } }}
        />
        <VictoryLegend
          data={legendData}
          centerTitle
          gutter={20}
          itemsPerRow={2}
          orientation="horizontal"
          rowGutter={{ top: 0, bottom: -10 }}
          style={{ title: { fontSize: 20 } }}
          titleOrientation="bottom"
          x={50}
          y={boundingRect.width * 0.81}
        />
      </VictoryChart>
    </div>
  );
};
Orangeman answered 26/1, 2023 at 16:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.