Categories
React

Add Charts into Our React App with Victory — Tooltips

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.

Tooltips

We can add tooltips to charts.

For example, we can write:

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

export default function App() {
  return (
    <div>
      <VictoryChart domain={{ x: [0, 11], y: [-10, 10] }}>
        <VictoryBar
          labelComponent={<VictoryTooltip />}
          data={[
            { x: 2, y: 5, label: "right-side-up" },
            { x: 4, y: -6, label: "upside-down" },
            { x: 6, y: 4, label: "tiny" },
            { x: 8, y: -5, label: "or a little n BIGGER" },
            { x: 10, y: 7, label: "automatically" }
          ]}
          style={{
            data: { fill: "tomato", width: 20 }
          }}
        />
      </VictoryChart>
      ​
    </div>
  );
}

We set the labelComponent to the VictoryTooltip component to show the tooltip.

Also, we can change the tooltip styles with a few props:

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

export default function App() {
  return (
    <div>
      <VictoryChart domain={{ x: [0, 11], y: [-10, 10] }}>
        <VictoryBar
          labelComponent={
            <VictoryTooltip
              cornerRadius={({ datum }) => (datum.x > 6 ? 0 : 20)}
              pointerLength={({ datum }) => (datum.y > 0 ? 5 : 20)}
              flyoutStyle={{
                stroke: ({ datum }) => (datum.x === 10 ? "tomato" : "black")
              }}
            />
          }
          data={[
            { x: 2, y: 5, label: "right-side-up" },
            { x: 4, y: -6, label: "upside-down" },
            { x: 6, y: 4, label: "tiny" },
            { x: 8, y: -5, label: "or a little n BIGGER" },
            { x: 10, y: 7, label: "automatically" }
          ]}
          style={{
            data: { fill: "tomato", width: 20 }
          }}
        />
      </VictoryChart>
      ​
    </div>
  );
}

VictoryVoronoiContainer

The VictoryVoronoiContainer lets us add tooltips to a line or to data points that are too small to hover over.

For instance, we can write:

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

export default function App() {
  return (
    <div>
      <VictoryChart
        domain={{ x: [0, 5], y: [-5, 5] }}
        containerComponent={<VictoryVoronoiContainer />}
      >
        <VictoryScatter
          style={{
            data: { fill: "tomato" },
            labels: { fill: "tomato" }
          }}
          size={({ active }) => (active ? 5 : 3)}
          labels={({ datum }) => datum.y}
          labelComponent={<VictoryTooltip />}
          data={[
            { x: 1, y: -4 },
            { x: 2, y: 4 },
            { x: 3, y: 2 },
            { x: 4, y: 1 }
          ]}
        />
        <VictoryScatter
          style={{
            data: { fill: "blue" },
            labels: { fill: "blue" }
          }}
          size={(datum, active) => (active ? 5 : 3)}
          labels={({ datum }) => datum.y}
          labelComponent={<VictoryTooltip />}
          data={[
            { x: 1, y: -3 },
            { x: 2, y: 3 },
            { x: 3, y: 3 },
            { x: 4, y: 0 }
          ]}
        />
        <VictoryScatter
          data={[
            { x: 1, y: 4 },
            { x: 2, y: -4 },
            { x: 3, y: -2 },
            { x: 4, y: -3 }
          ]}
          labels={({ datum }) => datum.y}
          labelComponent={<VictoryTooltip />}
          size={({ active }) => (active ? 5 : 3)}
        />
      </VictoryChart>
    </div>
  );
}

We set the containerComponent prop’s value to VictoryVoronoiContainer to add the tooltip.

The content is set by the labels prop.

Conclusion

We can add various kinds of tooltips to our charts with React Victory.

Categories
React

Add Charts into Our React App with Victory — Events and Layouts

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.

Simple Events

We can attach events straight onto the chart components.

For instance, we can write:

import React from "react";
import { Bar, VictoryBar } from "victory";

export default function App() {
  return (
    <VictoryBar
      data={[
        { x: 1, y: 2 },
        { x: 2, y: 4 },
        { x: 3, y: 7 },
        { x: 4, y: 3 },
        { x: 5, y: 5 }
      ]}
      dataComponent={
        <Bar
          events={{
            onClick: (evt) => alert(`(${evt.clientX}, ${evt.clientY})`)
          }}
        />
      }
    />
  );
}

to attach a click handler to the Bar component with the events prop.

We get the click coordinates with the clientX and clientY properties from the event object.

Events on Custom Components

Also, we can attach event handlers to custom components.

For instance, we can write:

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

const ScatterPoint = ({ x, y, datum }) => {
  const [selected, setSelected] = React.useState(false);
  const [hovered, setHovered] = React.useState(false);

return (
    <circle
      cx={x}
      cy={y}
      r={datum.x * datum.y}
      stroke={hovered ? "purple" : "white"}
      strokeWidth={2}
      fill={selected ? "cyan" : "magenta"}
      onClick={() => setSelected(!selected)}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
    />
  );
};

export default function App() {
  return (
    <VictoryChart>
      <VictoryScatter
        data={[
          { x: 1, y: 7 },
          { x: 2, y: 5 },
          { x: 3, y: 7 },
          { x: 4, y: 2 },
          { x: 5, y: 1 }
        ]}
        dataComponent={<ScatterPoint />}
      />
    </VictoryChart>
  );
}

to create the ScatterPoint component.

We add the onMouseEnter , onMouseLeave and onClick props to add the event handlers for those mouse events.

Layout

We can change the render order to change which component appears above which one.

For example, we can write:

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

export default function App() {
  return (
    <div>
      <VictoryChart>
        <VictoryScatter
          y={(data) => Math.sin(2 * Math.PI * data.x)}
          samples={25}
          size={5}
          style={{ data: { fill: "tomato" } }}
        />
        <VictoryLine
          style={{ data: { stroke: "orange" } }}
          y={(data) => Math.sin(2 * Math.PI * data.x)}
        />
        <VictoryAxis />
        <VictoryAxis dependentAxis />
      </VictoryChart>
    </div>
  );
}

to render the scatter points below the other components since it’s rendered first.

The items that are rendered earlier go below the ones that are rendered later.

VictoryPortal

We can also use the VictoryPortal component to render components in a top-level container.

This way, they appear above other components.

For instance, we wrap the VictoryLabel in the VictoryPortal :

import React from "react";
import {
  VictoryAxis,
  VictoryBar,
  VictoryChart,
  VictoryLabel,
  VictoryLine,
  VictoryPortal,
  VictoryScatter,
  VictoryStack
} from "victory";

export default function App() {
  return (
    <div>
      <VictoryChart domainPadding={40}>
        <VictoryStack
          colorScale={["gold", "orange", "tomato"]}
          style={{
            data: { width: 30 },
            labels: { padding: -20 }
          }}
          labelComponent={
            <VictoryPortal>
              <VictoryLabel />
            </VictoryPortal>
          }
        >
          <VictoryBar
            data={[
              { x: 1, y: 3, label: "C" },
              { x: 2, y: 4, label: "C" },
              { x: 3, y: 2, label: "C" }
            ]}
          />
          <VictoryBar
            data={[
              { x: 1, y: 3, label: "B" },
              { x: 2, y: 4, label: "B" },
              { x: 3, y: 2, label: "B" }
            ]}
          />
          <VictoryBar
            data={[
              { x: 1, y: 3, label: "A" },
              { x: 2, y: 4, label: "A" },
              { x: 3, y: 2, label: "A" }
            ]}
          />
        </VictoryStack>
        <VictoryAxis />
      </VictoryChart>
    </div>
  );
}

to render the labels above the other components.

Conclusion

We can render chart components in different orders and attach events to components with React Victory.

Categories
React

Add Charts into Our React App with Victory — Polar Charts

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.

Responsive VictoryContainer

We can set the responsive prop of the VictoryContainer component to render a responsive chart:

import React from "react";
import { VictoryChart, VictoryContainer, VictoryLine } from "victory";

export default function App() {
  return (
    <div>
      <VictoryChart
        height={200}
        width={300}
        containerComponent={<VictoryContainer responsive />}
      >
        <VictoryLine y={(data) => Math.sin(2 * Math.PI * data.x)} />
      </VictoryChart>
    </div>
  );
}

Rendering Components in Custom Containers

We can render components in custom containers.

For instance, we can write:

import React from "react";
import { VictoryLabel, VictoryPie } from "victory";

export default function App() {
  return (
    <svg viewBox="0 0 400 400">
      <VictoryPie
        standalone={false}
        width={400}
        height={400}
        data={[
          { x: "A", y: 10 },
          { x: "B", y: 20 },
          { x: "C", y: 80 }
        ]}
        innerRadius={70}
        labelRadius={100}
        style={{ labels: { fontSize: 20, fill: "white" } }}
      />
      <circle
        cx="200"
        cy="200"
        r="65"
        fill="none"
        stroke="black"
        strokeWidth={3}
      />
      <circle
        cx="200"
        cy="200"
        r="155"
        fill="none"
        stroke="black"
        strokeWidth={3}
      />
      <VictoryLabel
        textAnchor="middle"
        verticalAnchor="middle"
        x={200}
        y={200}
        style={{ fontSize: 30 }}
        text="Label"
      />
    </svg>
  );
}

to render the pie chart in the svg element.

This is because the chart components are rendered as svgs.

Polar Charts

We can add polar charts into our React app.

For instance, we can write:

import React from "react";
import {
  VictoryAxis,
  VictoryBar,
  VictoryChart,
  VictoryPolarAxis,
  VictoryTheme
} from "victory";
const data = [
  { x: 1, y: 3 },
  { x: 2, y: 4 },
  { x: 3, y: 2 }
];

export default function App() {
  return (
    <div>
      <VictoryChart polar domain={{ x: [0, 10] }} theme={VictoryTheme.material}>
        <VictoryPolarAxis tickCount={8} />
        <VictoryBar
          data={data}
          style={{ data: { fill: "#c43a31", stroke: "black", strokeWidth: 2 } }}
        />
      </VictoryChart>      ​
    </div>
  );
}

to add a polar chart with the VictoryChart component.

VictoryAxis has the axes for the chart.

VictoryBar are rendered in the chart as segments.

We can add the VictoryPolarAxis component to add the tick lines to the polar chart:

import React from "react";
import {
  VictoryBar,
  VictoryChart,
  VictoryPolarAxis,
  VictoryTheme
} from "victory";
const data = [
  { x: 1, y: 3 },
  { x: 2, y: 4 },
  { x: 3, y: 2 }
];

export default function App() {
  return (
    <div>
      <VictoryChart polar theme={VictoryTheme.material}>
        <VictoryPolarAxis
          dependentAxis
          style={{
            axis: { stroke: "none" },
            tickLabels: { fill: "none" },
            grid: { stroke: "grey", strokeDasharray: "4, 8" }
          }}
        />
        <VictoryPolarAxis tickValues={[0, 3, 6, 9]} />
        <VictoryBar
          style={{ data: { fill: "#c43a31", width: 50 } }}
          data={data}
        />
      </VictoryChart>
      ​
    </div>
  );
}

We can add multiple segments into the polar chart with the VictoryBar components:

import React from "react";
import {
  VictoryBar,
  VictoryChart,
  VictoryPolarAxis,
  VictoryStack,
  VictoryTheme
} from "victory";
const data = [
  { x: 1, y: 3 },
  { x: 2, y: 4 },
  { x: 3, y: 2 }
];

export default function App() {
  return (
    <div>
      <VictoryChart
        polar
        maxDomain={{ x: 360 }}
        height={250}
        width={250}
        padding={30}
      >
        <VictoryPolarAxis
          dependentAxis
          style={{
            axis: { stroke: "none" },
            tickLabels: { fill: "none" },
            grid: { stroke: "grey", strokeDasharray: "4, 8" }
          }}
        />
        <VictoryPolarAxis tickValues={[0, 45, 90, 135, 180, 225, 270, 315]} />
        <VictoryStack
          colorScale={["#ad1b11", "#c43a31", "#dc7a6b"]}
          style={{ data: { width: 50 } }}
        >
          <VictoryBar data={data} />
          <VictoryBar data={data} />
          <VictoryBar data={data} />
        </VictoryStack>
      </VictoryChart>
      ​
    </div>
  );
}

Conclusion

We can add various kinds of polar charts with React Victory.

Categories
React

Add Charts into Our React App with Victory — Shared and Dynamic Events

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.

VictorySharedEvents

We can add events shared between multiple charts with the VictorySharedEvents component.

For instance, we can write:

import React from "react";
import {
  VictoryBar,
  VictoryLabel,
  VictoryPie,
  VictorySharedEvents
} from "victory";

export default function App() {
  return (
    <svg viewBox="0 0 450 350">
      <VictorySharedEvents
        events={[
          {
            childName: ["pie", "bar"],
            target: "data",
            eventHandlers: {
              onMouseOver: () => {
                return [
                  {
                    childName: ["pie", "bar"],
                    mutation: (props) => {
                      return {
                        style: Object.assign({}, props.style, {
                          fill: "tomato"
                        })
                      };
                    }
                  }
                ];
              },
              onMouseOut: () => {
                return [
                  {
                    childName: ["pie", "bar"],
                    mutation: () => {
                      return null;
                    }
                  }
                ];
              }
            }
          }
        ]}
      >
        <g transform={"translate(150, 50)"}>
          <VictoryBar
            name="bar"
            width={300}
            standalone={false}
            style={{
              data: { width: 20 },
              labels: { fontSize: 25 }
            }}
            data={[
              { x: "a", y: 2 },
              { x: "b", y: 3 },
              { x: "c", y: 5 }
            ]}
            labels={["a", "b", "c"]}
            labelComponent={<VictoryLabel y={290} />}
          />
        </g>
        <g transform={"translate(0, -75)"}>
          <VictoryPie
            name="pie"
            width={250}
            standalone={false}
            style={{ labels: { fontSize: 25, padding: 10 } }}
            data={[
              { x: "a", y: 1 },
              { x: "b", y: 4 },
              { x: "c", y: 5 }
            ]}
          />
        </g>
      </VictorySharedEvents>
    </svg>
  );
}

In the events prop, we add an array with the eventsHandlers object to add event handlers for various events.

We have event handlers for mouseover with onMouseOver and one for mouseout with onMouseOut .

The mutation method lets us change the fill style of the segment we hover over.

childName has the name values of the charts we want to change.

Similarly, we have the onMouseOut event handler to return null to revert to the original style.

External Event Mutations

We can attach event mutations by changing states.

For instance, we can write:

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

const buttonStyle = {
  backgroundColor: "black",
  color: "white",
  padding: "10px",
  marginTop: "10px"
};

export default function App() {
  const [externalMutations, setExternalMutations] = useState({});
  const removeMutation = () => {
    setExternalMutations(undefined);
  };

const clearClicks = () => {
    setExternalMutations([
      {
        childName: "Bar-1",
        target: ["data"],
        eventKey: "all",
        mutation: () => ({ style: undefined }),
        callback: removeMutation
      }
    ]);
  };

return (
    <div>
      <button onClick={clearClicks} style={buttonStyle}>
        Reset
      </button>
      <VictoryChart
        domain={{ x: [0, 5] }}
        externalEventMutations={externalMutations}
        events={[
          {
            target: "data",
            childName: "Bar-1",
            eventHandlers: {
              onClick: () => ({
                target: "data",
                mutation: () => ({ style: { fill: "orange" } })
              })
            }
          }
        ]}
      >
        <VictoryBar
          name="Bar-1"
          style={{ data: { fill: "grey" } }}
          labels={() => "click me!"}
          data={[
            { x: 1, y: 2 },
            { x: 2, y: 4 },
            { x: 3, y: 1 },
            { x: 4, y: 5 }
          ]}
        />
      </VictoryChart>
    </div>
  );
}

to add click event handlers with the events prop on VictoryChart .

When we click on the bars, the fill changes to orange.

The Reset button calls clearClicks to clear all the click handlers by setting externalMutations to undefined .

clearClicks clear all the styles from the bars.

And we set externalEventMutations to externalMutations .

Conclusion

We can add event handlers dynamically and add shared events into charts with React Victory.

Categories
React

Add Charts into Our React App with Victory — Plot Functions and Events

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.

Plot Functions

We can plot functions in our React app with Victory easily.

For example, we can write:

import React from "react";
import { VictoryChart, VictoryLine } from "victory";

export default function App() {
  return (
    <VictoryChart>
      <VictoryLine
        samples={50}
        style={{ data: { stroke: "red", strokeWidth: 4 } }}
        y={(data) => Math.sin(2 * Math.PI * data.x)}
      />
    </VictoryChart>
  );
}

We set the samples prop to set the number of points to plot.

Then y is set to a function with the values we want to plot.

We get the x-axis value with data.x and do what we want with it.

Component Events

We can add event handlers for components in our charts.

For example, we can write:

import React from "react";
import { VictoryBar } from "victory";

export default function App() {
  return (
    <VictoryBar
      data={[
        { x: 1, y: 2, label: "A" },
        { x: 2, y: 4, label: "B" },
        { x: 3, y: 7, label: "C" },
        { x: 4, y: 3, label: "D" },
        { x: 5, y: 5, label: "E" }
      ]}
      events={[
        {
          target: "data",
          eventHandlers: {
            onClick: () => {
              return [
                {
                  target: "labels",
                  mutation: (props) => {
                    return props.text === "clicked"
                      ? null
                      : { text: "clicked" };
                  }
                }
              ];
            }
          }
        }
      ]}
    />
  );
}

to add the events prop into our VictoryBar component.

In it, we add the eventHandlers.onClick function to add click handlers to each bar.

Then in the mutation method, we toggle the ‘clicked’ text as we click the bars.

Nested Component Events

We can trigger change in one part of the chart from other parts of the chart.

For instance, we can write:

import React from "react";
import { VictoryArea, VictoryBar, VictoryChart, VictoryStack } from "victory";

export default function App() {
  return (
    <VictoryChart
      events={[
        {
          childName: ["area-1", "area-2"],
          target: "data",
          eventHandlers: {
            onClick: () => {
              return [
                {
                  childName: "area-4",
                  mutation: (props) => {
                    const fill = props.style.fill;
                    return fill === "green"
                      ? null
                      : { style: { fill: "green" } };
                  }
                }
              ];
            }
          }
        }
      ]}
    >
      <VictoryStack>
        <VictoryArea
          name="area-1"
          data={[
            { x: "a", y: 2 },
            { x: "b", y: 3 },
            { x: "c", y: 5 },
            { x: "d", y: 4 }
          ]}
        />
        <VictoryArea
          name="area-2"
          data={[
            { x: "a", y: 1 },
            { x: "b", y: 4 },
            { x: "c", y: 5 },
            { x: "d", y: 7 }
          ]}
        />
        <VictoryArea
          name="area-3"
          data={[
            { x: "a", y: 3 },
            { x: "b", y: 2 },
            { x: "c", y: 6 },
            { x: "d", y: 2 }
          ]}
        />
        <VictoryArea
          name="area-4"
          data={[
            { x: "a", y: 2 },
            { x: "b", y: 3 },
            { x: "c", y: 3 },
            { x: "d", y: 4 }
          ]}
        />
      </VictoryStack>
    </VictoryChart>
  );
}

We have 4 VictoryArea components to display filled areas formed from the points.

Then we add the events prop to VictoryChart .

childName has the name values of the components that triggers the mutation function.

Then in the onClick method we return an array with objects that specifies which component changes and how they change.

childName has the name of the component that changes.

mutation has the code to change the component specified in childName in the array returned by onClick .

We toggle the fill between 'green' and null on the VictoryArea with name area-4 .

Conclusion

We can plot functions and listen for events in chart components in React Victory’s charts.