Spider Chart in Victory Native

118 views Asked by At

I'm trying to create a spider chart in Victory Native but I need the edges of the radar axis(VictoryPolarAxis) to be straight like this

The chart I expect looks like this:

spider chart

Thank for your help!

1

There are 1 answers

0
Ashish Shevale On

The trick here is to draw a line chart in polar coordinates and then use Victory's customization api to draw the straight lines you need.

Output of Polar Chart Image for below code

Refer to the following code

import "./styles.css";
import {
  VictoryChart,
  VictoryLine,
  VictoryPolarAxis,
  VictoryTheme
} from "victory";
import React from "react";

const sampleDataPolar = [
  { x: "E", y: 1 },
  { x: "NE", y: 1.9 },
  { x: "N", y: 1.5 },
  { x: "NW", y: 2 },
  { x: "W", y: 2.1 },
  { x: "SW", y: 1.8 },
  { x: "S", y: 1.9 },
  { x: "SE", y: 0.7 },
  { x: "E", y: 1 }
];

function CircularAxisComponent(props) {
  const centerX = props.cx;
  const centerY = props.cy;
  const radius = props.r;
  const angularGap = 360 / (sampleDataPolar.length - 1);
  const pts = Array(sampleDataPolar.length)
    .fill(0)
    .map((_, idx) => {
      const angle_deg = angularGap * idx;
      const angle_rad = (Math.PI / 180) * angle_deg;

      const pointX = centerX + radius * Math.cos(angle_rad);
      const pointY = centerY + radius * Math.sin(angle_rad);
      return `${pointX},${pointY}`;
    })
    .join(",");
  return <polygon points={pts} fill="none" stroke="lightgrey" />;
}

export default function App() {
  return (
    <div className="App">
      <VictoryChart
        polar
        theme={VictoryTheme.material}
        domainPadding={{ y: 40 }}
      >
        <VictoryPolarAxis
          tickCount={8}
          circularAxisComponent={<CircularAxisComponent />}
        />

        <VictoryLine
          data={sampleDataPolar}
          style={{ data: { fill: "transparent", strokeWidth: 2 } }}
          polar
        />
      </VictoryChart>
    </div>
  );
}

Let's dive in.

Creating a line chart in polar form is fairly easy. Just pass your data to the VictoryLine component and set the polar property to true.

For replacing the circular arc of the axis with straight lines, use the VictoryPolarAxis. In the example above, this component takes a prop called circularAxisComponent that allows us to customize how the axis is rendered.

I created a functional component called CircularAxisComponent that draws this axis.

All this component does is render a SVG polygon. Getting the coordinates of the point requires a bit of maths and trigonometry.

const pointX = centerX + radius * Math.cos(angle_rad);
const pointY = centerY + radius * Math.sin(angle_rad);

In the calculation for pointX, radius * cos(t) gives the X coordinate and adding centerX will translate this point so that the resulting polygon appears at the correct position. Same for y coordinate.

To checkout other ways you can customize the Polar Axis component, refer to the docs - Victory Docs - VictoryPolarAxis