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.