Categories
React

Add Charts into Our React App with Victory — Transition, Brush and Zoom

Spread the love

The Victory lets us add charts and data visualization into our React app.

In this article, we’ll look at how to add charts into our React app with Victory.

Transitions

We can set the transition effects for animations with the VictoryBar component.

For instance, we can write:

import React, { useEffect, useState } from "react";
import { VictoryBar, VictoryChart } from "victory";

const random = (min, max) => Math.floor(min + Math.random() * max);

const getData = () => {
  const bars = random(6, 10);
  return Array(bars)
    .fill()
    .map((_, index) => {
      return {
        x: index + 1,
        y: random(2, 100)
      };
    });
};

export default function App() {
  const [data, setData] = useState([]);
  useEffect(() => {
    const timer = setInterval(() => {
      setData(getData());
    }, 3000);
    return () => clearInterval(timer);
  }, []);

  return (
    <VictoryChart domainPadding={{ x: 20 }} animate={{ duration: 500 }}>
      <VictoryBar
        data={data}
        style={{
          data: { fill: "tomato", width: 12 }
        }}
        animate={{
          onExit: {
            duration: 500,
            before: () => ({
              _y: 0,
              fill: "orange",
              label: "BYE"
            })
          }
        }}
      />
    </VictoryChart>
  );
}

We generate random data for our graph and update it with the new data every 3 seconds.

We set the animate prop on the VictoryBar component to add transition effects for the bars.

onExit.duration has the duration of the leave animation.

We change the color of the bars with fill property.

And the label is displayed when the bars leave the screen.

Brush and Zoom

We can add brush and zoom into our charts with the VictoryChart‘s containerComponent prop.

For instance, we can write:

import React from "react";
import { VictoryChart, VictoryScatter, VictoryZoomContainer } from "victory";

const random = (min, max) => Math.floor(min + Math.random() * max);

const getData = () => {
  return Array(50)
    .fill()
    .map((index) => {
      return {
        x: random(1, 50),
        y: random(10, 90),
        size: random(8) + 3
      };
    });
};

export default function App() {
  return (
    <VictoryChart
      domain={{ y: [0, 100] }}
      containerComponent={
        <VictoryZoomContainer zoomDomain={{ x: [5, 35], y: [0, 100] }} />
      }
    >
      <VictoryScatter
        data={getData()}
        style={{
          data: {
            opacity: ({ datum }) => (datum.y % 5 === 0 ? 1 : 0.7),
            fill: ({ datum }) => (datum.y % 5 === 0 ? "tomato" : "black")
          }
        }}
      />
    </VictoryChart>
  );
}

We set containerComponent to the VictoryZoomContainer component.

The zoomDomain prop lets us set the zoom level range for the x and y axes with the x and y properties.

We can also create a separate chart for the brush:

import React, { useState } from "react";
import {
  VictoryAxis,
  VictoryBrushContainer,
  VictoryChart,
  VictoryLine,
  VictoryZoomContainer
} from "victory";

export default function App() {
  const [selectedDomain, setSelectedDomain] = useState();
  const [zoomDomain, setZoomDomain] = useState();

const handleZoom = (domain) => {
    setSelectedDomain(domain);
  };

const handleBrush = (domain) => {
    setZoomDomain(domain);
  };

return (
    <>
      <VictoryChart
        width={550}
        height={300}
        scale={{ x: "time" }}
        containerComponent={
          <VictoryZoomContainer
            responsive={false}
            zoomDimension="x"
            zoomDomain={zoomDomain}
            onZoomDomainChange={handleZoom}
          />
        }
      >
        <VictoryLine
          style={{
            data: { stroke: "tomato" }
          }}
          data={[
            { x: new Date(1982, 1, 1), y: 125 },
            { x: new Date(1987, 1, 1), y: 257 },
            { x: new Date(1993, 1, 1), y: 345 },
            { x: new Date(1997, 1, 1), y: 515 },
            { x: new Date(2001, 1, 1), y: 132 },
            { x: new Date(2005, 1, 1), y: 305 },
            { x: new Date(2011, 1, 1), y: 270 },
            { x: new Date(2015, 1, 1), y: 470 }
          ]}
        />
      </VictoryChart>

<VictoryChart
        width={550}
        height={90}
        scale={{ x: "time" }}
        padding={{ top: 0, left: 50, right: 50, bottom: 30 }}
        containerComponent={
          <VictoryBrushContainer
            responsive={false}
            brushDimension="x"
            brushDomain={selectedDomain}
            onBrushDomainChange={handleBrush}
          />
        }
      >
        <VictoryAxis
          tickValues={[
            new Date(1985, 1, 1),
            new Date(1990, 1, 1),
            new Date(1995, 1, 1),
            new Date(2000, 1, 1),
            new Date(2005, 1, 1),
            new Date(2010, 1, 1),
            new Date(2015, 1, 1)
          ]}
          tickFormat={(x) => new Date(x).getFullYear()}
        />
        <VictoryLine
          style={{
            data: { stroke: "tomato" }
          }}
          data={[
            { x: new Date(1982, 1, 1), y: 125 },
            { x: new Date(1987, 1, 1), y: 257 },
            { x: new Date(1993, 1, 1), y: 345 },
            { x: new Date(1997, 1, 1), y: 515 },
            { x: new Date(2001, 1, 1), y: 132 },
            { x: new Date(2005, 1, 1), y: 305 },
            { x: new Date(2011, 1, 1), y: 270 },
            { x: new Date(2015, 1, 1), y: 470 }
          ]}
        />
      </VictoryChart>
    </>
  );
}

We do this by setting the zoomDomain and the selectedDomain by dragging on the bottom graph.

In the bottom VictoryChart , we have the containerComponent set to the VictoryBrushContainer .

brushDomain is set to the selectedDomain ,

And the onBrushDomainChange is set to the handleBrush function to change selectedDomain .

The location will be reflected in the top chart.

We have similar code to set the zoomDomain in the top chart.

The zoom is reflected in the bottom chart.

Conclusion

We can add transitions, brush, and zoom into charts in our React app with Victory.

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 *