Categories
React

Add Charts into Our React App with Nivo — Bar 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 Nivo.

Bar Charts

We can add bar charts into our React app with Nivo.

First, we have to install the @nivo/bar package by running:

npm i @nivo/bar

Then we can add the bar chart by writing:

import React from "react";
import { ResponsiveBar } from "@nivo/bar";

const data = [
  {
    country: "AD",
    "hot dog": 81,
    "hot dogColor": "hsl(154, 70%, 50%)",
    burger: 193,
    burgerColor: "hsl(304, 70%, 50%)",
    sandwich: 50,
    sandwichColor: "hsl(222, 70%, 50%)",
    kebab: 154,
    kebabColor: "hsl(241, 70%, 50%)",
    fries: 68,
    friesColor: "hsl(331, 70%, 50%)",
    donut: 49,
    donutColor: "hsl(259, 70%, 50%)"
  },
  {
    country: "AE",
    "hot dog": 46,
    "hot dogColor": "hsl(33, 70%, 50%)",
    burger: 96,
    burgerColor: "hsl(70, 70%, 50%)",
    sandwich: 10,
    sandwichColor: "hsl(348, 70%, 50%)",
    kebab: 18,
    kebabColor: "hsl(191, 70%, 50%)",
    fries: 93,
    friesColor: "hsl(262, 70%, 50%)",
    donut: 54,
    donutColor: "hsl(118, 70%, 50%)"
  },
  {
    country: "AF",
    "hot dog": 123,
    "hot dogColor": "hsl(17, 70%, 50%)",
    burger: 24,
    burgerColor: "hsl(122, 70%, 50%)",
    sandwich: 12,
    sandwichColor: "hsl(35, 70%, 50%)",
    kebab: 141,
    kebabColor: "hsl(102, 70%, 50%)",
    fries: 33,
    friesColor: "hsl(191, 70%, 50%)",
    donut: 8,
    donutColor: "hsl(183, 70%, 50%)"
  }
];

const MyResponsiveBar = ({ data }) => (
  <ResponsiveBar
    data={data}
    keys={["hot dog", "burger", "sandwich", "kebab", "fries", "donut"]}
    indexBy="country"
    margin={{ top: 50, right: 130, bottom: 50, left: 60 }}
    padding={0.3}
    valueScale={{ type: "linear" }}
    indexScale={{ type: "band", round: true }}
    colors={{ scheme: "nivo" }}
    defs={[
      {
        id: "dots",
        type: "patternDots",
        background: "inherit",
        color: "#38bcb2",
        size: 4,
        padding: 1,
        stagger: true
      },
      {
        id: "lines",
        type: "patternLines",
        background: "inherit",
        color: "#eed312",
        rotation: -45,
        lineWidth: 6,
        spacing: 10
      }
    ]}
    fill={[
      {
        match: {
          id: "fries"
        },
        id: "dots"
      },
      {
        match: {
          id: "sandwich"
        },
        id: "lines"
      }
    ]}
    borderColor={{ from: "color", modifiers: [["darker", 1.6]] }}
    axisTop={null}
    axisRight={null}
    axisBottom={{
      tickSize: 5,
      tickPadding: 5,
      tickRotation: 0,
      legend: "country",
      legendPosition: "middle",
      legendOffset: 32
    }}
    axisLeft={{
      tickSize: 5,
      tickPadding: 5,
      tickRotation: 0,
      legend: "food",
      legendPosition: "middle",
      legendOffset: -40
    }}
    labelSkipWidth={12}
    labelSkipHeight={12}
    labelTextColor={{ from: "color", modifiers: [["darker", 1.6]] }}
    legends={[
      {
        dataFrom: "keys",
        anchor: "bottom-right",
        direction: "column",
        justify: false,
        translateX: 120,
        translateY: 0,
        itemsSpacing: 2,
        itemWidth: 100,
        itemHeight: 20,
        itemDirection: "left-to-right",
        itemOpacity: 0.85,
        symbolSize: 20,
        effects: [
          {
            on: "hover",
            style: {
              itemOpacity: 1
            }
          }
        ]
      }
    ]}
    animate={true}
    motionStiffness={90}
    motionDamping={15}
  />
);

export default function App() {
  return (
    <div style={{ height: 300, width: 400 }}>
      <MyResponsiveBar data={data} />
    </div>
  );
}

The data array has an array with the key names for each bar segment.

The numbers are the values, and the strings are the color codes for each bar segment.

Next, we add the MyResponsiveBar component and render the ResponsiveBar component inside.

The keys array has the keys for the bar segments.

margin has the margins.

valueScale has the scale for the values. linear scale doesn’t transform the values.

defs have the fill pattern definitions for the bar segments.

color have the background color for each pattern.

fill have the id of the fill patterns that we defined in defs set.

axisBottom has the settings for the x-axis.

We set the tick size, tick padding, legend has the x-axis text.

axisLeft has the settings for the y-axis.

We have the same settings set.

legends have the legend settings.

We set the anchor property to the location of the legend.

And we set the itemSpacing , itemWidth , itemHeight and itemDirection to set the legend items styles.

In the effects property, we have the on property to set when the effect is applied and set the itemOpacity when we hover over the legend.

We also have the animate prop to enable animation, and motionStiffness and motionDamping to set the animation settings.

Conclusion

We can add bar charts into our React app with Nivo.

Categories
React

Add Charts into Our React App with Victory — Tooltip Customization

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.

Mouse Following Tooltip

We can add a tooltip with a pointer that stretches when we move the mouse.

To add it, we write:

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

export default function App() {
  return (
    <VictoryChart
      domain={{ y: [0, 6] }}
      containerComponent={
        <VictoryVoronoiContainer
          mouseFollowTooltips
          voronoiDimension="x"
          labels={({ datum }) => `y: ${datum.y}`}
        />
      }
    >
      <VictoryScatter
        style={{ data: { fill: "red" }, labels: { fill: "red" } }}
        data={[
          { x: 0, y: 2 },
          { x: 2, y: 3 },
          { x: 4, y: 4 },
          { x: 6, y: 5 }
        ]}
      />
      <VictoryScatter
        data={[
          { x: 2, y: 2 },
          { x: 4, y: 3 },
          { x: 6, y: 4 },
          { x: 8, y: 5 }
        ]}
      />
    </VictoryChart>
  );
}

We add the mouseFollowTooltips prop to the VictoryVoronoiContainer component to add this feature.

Also, we can listen to other events with the events prop.

For instance, we can write:

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

export default function App() {
  return (
    <VictoryChart domain={{ x: [0, 11], y: [-10, 10] }}>
      <VictoryBar
        labelComponent={<VictoryTooltip />}
        data={[
          { x: 2, y: 5, label: "A" },
          { x: 4, y: -6, label: "B" },
          { x: 6, y: 4, label: "C" },
          { x: 8, y: -5, label: "D" },
          { x: 10, y: 7, label: "E" }
        ]}
        style={{
          data: { fill: "tomato", width: 20 }
        }}
        events={[
          {
            target: "data",
            eventHandlers: {
              onMouseOver: () => {
                return [
                  {
                    target: "data",
                    mutation: () => ({ style: { fill: "gold", width: 30 } })
                  },
                  {
                    target: "labels",
                    mutation: () => ({ active: true })
                  }
                ];
              },
              onMouseOut: () => {
                return [
                  {
                    target: "data",
                    mutation: () => {}
                  },
                  {
                    target: "labels",
                    mutation: () => ({ active: false })
                  }
                ];
              }
            }
          }
        ]}
      />
    </VictoryChart>
  );
}

We have the onMouseOver and onMouseOut properties with the target property to set which item to mutate.

And the mutation method to change the styles by returning an object with the styles we want.

Custom Tooltip

We can add a custom tooltip by creating our own tooltip component.

For instance, we can write:

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

const CustomTooltip = (props) => {
  const { x, y } = props;
  const rotation = `rotate(-45 ${x} ${y})`;
  return (
    <g transform={rotation}>
      <VictoryTooltip {...props} renderInPortal={false} />
    </g>
  );
};
CustomTooltip.defaultEvents = VictoryTooltip.defaultEvents;

export default function App() {
  return (
    <VictoryChart domain={{ x: [0, 11], y: [-10, 10] }}>
      <VictoryBar
        labelComponent={<CustomTooltip />}
        data={[
          { x: 2, y: 5, label: "A" },
          { x: 4, y: -6, label: "B" },
          { x: 6, y: 4, label: "C" },
          { x: 8, y: -5, label: "D" },
          { x: 10, y: 7, label: "E" }
        ]}
        style={{
          data: { fill: "tomato", width: 20 }
        }}
      />
    </VictoryChart>
  );
}

to create the CustomTooltip component.

We have to set the defaultEvents property to VictoryTooltip.defaultEvents for the tooltip to work since it adds the required event handlers for the tooltip.

Conclusion

We can add a mouse following tooltip and custom tooltips into our React charts with Victory.

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.