Categories
Visx

Create a React Horizontal Grouped Bar Chart with the Visx Library

Spread the love

Visx is a library that lets us add graphics to our React app easily.

In this article, we’ll look at how to use it to add horizontal grouped bar charts into our React app.

Install Required Packages

We have to install a few modules to create the grouped bar chart.

To get started, we run:

npm i @visx/axis @visx/group @visx/mock-data @visx/responsive @visx/scale @visx/shape

to install the packages.

Create the Chart

We can create the chart by adding the items provided by the modules.

We use the data from the @visx/mock-data module.

To create the chart, we write:

import React from "react";
import { BarGroupHorizontal, Bar } from "@visx/shape";
import { Group } from "@visx/group";
import { AxisLeft } from "@visx/axis";
import cityTemperature from "@visx/mock-data/lib/mocks/cityTemperature";
import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale";
import { timeParse, timeFormat } from "d3-time-format";

const blue = "#aeeef8";
const green = "#e5fd3d";
const purple = "#9caff6";
const background = "#612efb";
const defaultMargin = { top: 20, right: 20, bottom: 20, left: 50 };

const parseDate = timeParse("%Y-%m-%d");
const format = timeFormat("%b %d");
const formatDate = (date) => format(parseDate(date));
function max(arr, fn) {
  return Math.max(...arr.map(fn));
}

const data = cityTemperature.slice(0, 4);
const keys = Object.keys(data[0]).filter((d) => d !== "date");

const getDate = (d) => d.date;

const dateScale = scaleBand({
  domain: data.map(getDate),
  padding: 0.2
});
const cityScale = scaleBand({
  domain: keys,
  padding: 0.1
});
const tempScale = scaleLinear({
  domain: [0, max(data, (d) => max(keys, (key) => Number(d[key])))]
});
const colorScale = scaleOrdinal({
  domain: keys,
  range: [blue, green, purple]
});

function Example({ width, height, margin = defaultMargin, events = false }) {
  const xMax = width - margin.left - margin.right;
  const yMax = height - margin.top - margin.bottom;

dateScale.rangeRound([0, yMax]);
  cityScale.rangeRound([0, dateScale.bandwidth()]);
  tempScale.rangeRound([0, xMax]);

return width < 10 ? null : (
    <svg width={width} height={height}>
      <rect
        x={0}
        y={0}
        width={width}
        height={height}
        fill={background}
        rx={14}
      />
      <Group top={margin.top} left={margin.left}>
        <BarGroupHorizontal
          data={data}
          keys={keys}
          width={xMax}
          y0={getDate}
          y0Scale={dateScale}
          y1Scale={cityScale}
          xScale={tempScale}
          color={colorScale}
        >
          {(barGroups) =>
            barGroups.map((barGroup) => (
              <Group
                key={`bar-group-horizontal-${barGroup.index}-${barGroup.y0}`}
                top={barGroup.y0}
              >
                {barGroup.bars.map((bar) => (
                  <Bar
                    key={`${barGroup.index}-${bar.index}-${bar.key}`}
                    x={bar.x}
                    y={bar.y}
                    width={bar.width}
                    height={bar.height}
                    fill={bar.color}
                    rx={4}
                    onClick={() => {
                      if (events)
                        alert(
                          `${bar.key} (${bar.value}) - ${JSON.stringify(bar)}`
                        );
                    }}
                  />
                ))}
              </Group>
            ))
          }
        </BarGroupHorizontal>
        <AxisLeft
          scale={dateScale}
          stroke={green}
          tickStroke={green}
          tickFormat={formatDate}
          hideAxisLine
          tickLabelProps={() => ({
            fill: green,
            fontSize: 11,
            textAnchor: "end",
            dy: "0.33em"
          })}
        />
      </Group>
    </svg>
  );
}

export default function App() {
  return (
    <div className="App">
      <Example width="500" height="300" />
    </div>
  );
}

We set the colors of the bars with the blue , green and purple variables.

The background variable has the background color.

defaultMargin have the default margins.

parseDate and format have the date parsing and formatting functions.

We parse the date from the mock data so we can format them to display in the chart.

data has the data for the chart.

keys have the data for the x-axis.

dateScale have the date scale.

cityScale have the city data.

tempScale have the temperature values for the bars.

colorScale have the colors for the bars.

We computed the xMax and yMax values to get the max values for the x and y axes.

Then we call rangeRound to set the max values for the x and y-axis ranges.

Next, we return the svg element and add the chart parts inside to add the bar.

The Group component is the container for the bar parts.

BarGroupHorizontal lets us display the bar groups horizontally.

We set the color , width , and the scales for the bars with the y0 , y0Scale and y1Scale props.

xScale sets the x-axis scale which is the bar scale.

Then we map the barGroups to return the Bar s in the map callback.

We set the bar lengths with the width prop.

Finally, we add the AxisLeft component to render the y-axis.

Conclusion

We can use the modules provided by Visx to create a horizontal grouped bar chart in our React app.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

One reply on “Create a React Horizontal Grouped Bar Chart with the Visx Library”

Leave a Reply

Your email address will not be published. Required fields are marked *