Categories
Visx

Create a React Area Difference 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 area difference charts into our React app.

Install Required Libraries

We’ve to install multiple modules provided by the Visx library to create the Area Difference Chart.

To do this, we run:

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

Create the Chart

Once we installed all the required libraries, we add the chart by writing:

import React from "react";
import { Group } from "@visx/group";
import { curveBasis } from "@visx/curve";
import { LinePath } from "@visx/shape";
import { Threshold } from "@visx/threshold";
import { scaleTime, scaleLinear } from "@visx/scale";
import { AxisLeft, AxisBottom } from "@visx/axis";
import { GridRows, GridColumns } from "@visx/grid";
import cityTemperature from "@visx/mock-data/lib/mocks/cityTemperature";

export const background = "#f3f3f3";

const date = (d) => new Date(d.date).valueOf();
const ny = (d) => Number(d["New York"]);
const sf = (d) => Number(d["San Francisco"]);

const timeScale = scaleTime({
  domain: [
    Math.min(...cityTemperature.map(date)),
    Math.max(...cityTemperature.map(date))
  ]
});
const temperatureScale = scaleLinear({
  domain: [
    Math.min(...cityTemperature.map((d) => Math.min(ny(d), sf(d)))),
    Math.max(...cityTemperature.map((d) => Math.max(ny(d), sf(d))))
  ],
  nice: true
});

const defaultMargin = { top: 40, right: 30, bottom: 50, left: 40 };

function Theshold({ width, height, margin = defaultMargin }) {
  if (width < 10) return null;

const xMax = width - margin.left - margin.right;
  const yMax = height - margin.top - margin.bottom;

timeScale.range([0, xMax]);
  temperatureScale.range([yMax, 0]);

return (
    <div>
      <svg width={width} height={height}>
        <rect
          x={0}
          y={0}
          width={width}
          height={height}
          fill={background}
          rx={14}
        />
        <Group left={margin.left} top={margin.top}>
          <GridRows
            scale={temperatureScale}
            width={xMax}
            height={yMax}
            stroke="#e0e0e0"
          />
          <GridColumns
            scale={timeScale}
            width={xMax}
            height={yMax}
            stroke="#e0e0e0"
          />
          <line x1={xMax} x2={xMax} y1={0} y2={yMax} stroke="#e0e0e0" />
          <AxisBottom
            top={yMax}
            scale={timeScale}
            numTicks={width > 520 ? 10 : 5}
          />
          <AxisLeft scale={temperatureScale} />
          <text x="-70" y="15" transform="rotate(-90)" fontSize={10}>
            Temperature (°F)
          </text>
          <Threshold
            id={`${Math.random()}`}
            data={cityTemperature}
            x={(d) => timeScale(date(d)) ?? 0}
            y0={(d) => temperatureScale(ny(d)) ?? 0}
            y1={(d) => temperatureScale(sf(d)) ?? 0}
            clipAboveTo={0}
            clipBelowTo={yMax}
            curve={curveBasis}
            belowAreaProps={{
              fill: "violet",
              fillOpacity: 0.4
            }}
            aboveAreaProps={{
              fill: "green",
              fillOpacity: 0.4
            }}
          />
          <LinePath
            data={cityTemperature}
            curve={curveBasis}
            x={(d) => timeScale(date(d)) ?? 0}
            y={(d) => temperatureScale(sf(d)) ?? 0}
            stroke="#222"
            strokeWidth={1.5}
            strokeOpacity={0.8}
            strokeDasharray="1,2"
          />
          <LinePath
            data={cityTemperature}
            curve={curveBasis}
            x={(d) => timeScale(date(d)) ?? 0}
            y={(d) => temperatureScale(ny(d)) ?? 0}
            stroke="#222"
            strokeWidth={1.5}
          />
        </Group>
      </svg>
    </div>
  );
}

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

We use the mock data provided by the Visx library to create the chart.

We create the timeScale scale for the x-axis.

And we create the temperatureScale for the y-axis.

We call scaleTime and scaleLinear respectively to scale the data to display the chart.

Next, we set the margins with the defaultMargin object.

Then we create the Threshold component which has the area difference chart.

In it, we computed the xMax and yMax values to create the max value for the x and y axes respectively.

Then we call the range method to create the time and temperature scales for the chart.

Next, we add the svg element to add the container for the chart.

rect has the rectangle that surrounds the chart.

Group has items we need to form the chart.

GridRows has the grid rows.

We set the scale prop to the temperatureScale to display the temperatures.

Likewise, we do the same for the GridColumns component but scale is set to timeScale .

line has the perimeter lines for the chart.

AxisBottom has the x-axis.

AxisLeft is the y-axis.

We add the Threshold component to bad the fill between the lines.

And we add the lines with the LinePath component.

We set the data by setting the data prop.

The x and y props return the x and y values.

Finally, in App , we render the Threshold component we created and set the width and height to display the chart.

Conclusion

We can create area difference charts easily in our React app with the Visx library.

By John Au-Yeung

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

Leave a Reply

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