Visx - это библиотека, которая позволяет нам легко добавлять графику в наше приложение React.

В этой статье мы рассмотрим, как использовать его для добавления радарных диаграмм в наше приложение React.

Установить необходимые пакеты

Пришлось установить несколько модулей.

Для начала запускаем:

npm i @visx/group @visx/mock-data @visx/responsive @visx/point @visx/scale @visx/shape

для установки пакетов.

Радарная диаграмма

Для создания радиолокационной карты пишем:

import React from "react";
import { Group } from "@visx/group";
import letterFrequency from "@visx/mock-data/lib/mocks/letterFrequency";
import { scaleLinear } from "@visx/scale";
import { Point } from "@visx/point";
import { Line, LineRadial } from "@visx/shape";
const orange = "#ff9933";
const pumpkin = "#f5810c";
const silver = "#d9d9d9";
const background = "#FAF7E9";
const degrees = 360;
const data = letterFrequency.slice(2, 12);
const y = (d) => d.frequency;
const genAngles = (length) =>
  [...new Array(length + 1)].map((_, i) => ({
    angle: i * (degrees / length)
  }));
const genPoints = (length, radius) => {
  const step = (Math.PI * 2) / length;
  return [...new Array(length)].map((_, i) => ({
    x: radius * Math.sin(i * step),
    y: radius * Math.cos(i * step)
  }));
};
function genPolygonPoints(dataArray, scale, getValue) {
  const step = (Math.PI * 2) / dataArray.length;
  const points = new Array(dataArray.length).fill({
    x: 0,
    y: 0
  });
  const pointString = new Array(dataArray.length + 1)
    .fill("")
    .reduce((res, _, i) => {
      if (i > dataArray.length) return res;
      const xVal = scale(getValue(dataArray[i - 1])) * Math.sin(i * step);
      const yVal = scale(getValue(dataArray[i - 1])) * Math.cos(i * step);
      points[i - 1] = { x: xVal, y: yVal };
      res += `${xVal},${yVal} `;
      return res;
    });
  return { points, pointString };
}
const defaultMargin = { top: 40, left: 80, right: 80, bottom: 80 };
function Example({ width, height, levels = 5, margin = defaultMargin }) {
  const xMax = width - margin.left - margin.right;
  const yMax = height - margin.top - margin.bottom;
  const radius = Math.min(xMax, yMax) / 2;
const radialScale = scaleLinear({
    range: [0, Math.PI * 2],
    domain: [degrees, 0]
  });
const yScale = scaleLinear({
    range: [0, radius],
    domain: [0, Math.max(...data.map(y))]
  });
const webs = genAngles(data.length);
  const points = genPoints(data.length, radius);
  const polygonPoints = genPolygonPoints(data, (d) => yScale(d) ?? 0, y);
  const zeroPoint = new Point({ x: 0, y: 0 });
  return width < 10 ? null : (
    <svg width={width} height={height}>
      <rect fill={background} width={width} height={height} rx={14} />
      <Group top={height / 2 - margin.top} left={width / 2}>
        {[...new Array(levels)].map((_, i) => (
          <LineRadial
            key={`web-${i}`}
            data={webs}
            angle={(d) => radialScale(d.angle) ?? 0}
            radius={((i + 1) * radius) / levels}
            fill="none"
            stroke={silver}
            strokeWidth={2}
            strokeOpacity={0.8}
            strokeLinecap="round"
          />
        ))}
        {[...new Array(data.length)].map((_, i) => (
          <Line
            key={`radar-line-${i}`}
            from={zeroPoint}
            to={points[i]}
            stroke={silver}
          />
        ))}
        <polygon
          points={polygonPoints.pointString}
          fill={orange}
          fillOpacity={0.3}
          stroke={orange}
          strokeWidth={1}
        />
        {polygonPoints.points.map((point, i) => (
          <circle
            key={`radar-point-${i}`}
            cx={point.x}
            cy={point.y}
            r={4}
            fill={pumpkin}
          />
        ))}
      </Group>
    </svg>
  );
}
export default function App() {
  return (
    <div className="App">
      <Example width={500} height={300} />
    </div>
  );
}

Мы определяем переменные с помощью цветов диаграммы в качестве значений.

degrees имеет градусы для радиолокационной карты.

data содержит данные для диаграммы.

y - это геттер, который позволяет нам получать значения по оси Y.

genAngles позволяет нам создавать углы для диаграммы, а genPoints создавать точки.

genPolygonPoints генерировать точки для радиолокационной карты.

Затем, чтобы создать диаграмму радара, мы добавляем компонент LineRadial, чтобы добавить сеть для диаграммы радара.

Углы мы получаем из функции radialScale.

radius вычисляется из опоры radius.

Сегменты линии для графика создаются с помощью компонента Line.

polygon позволяет нам создать полигональную заливку для радиолокационной карты.

circle в обратном вызове polygonPoints.map создает точки, расположенные под углами.

Заключение

Мы можем легко добавить радарные диаграммы в наше приложение React с помощью библиотеки Visx.