Использование React и Recharts для создания интерактивной панели инструментов

В этой статье мы сосредоточимся на библиотеке Recharts для создания интерактивных 2D-диаграмм. Для этого мы будем использовать Covid-19 api, чтобы отображать не только данные Covid19 для сравнения стран, но и показывать исторические данные каждой страны. Сначала мы создадим таблицу, показывающую все страны, и используем функцию щелчка, чтобы показать исторические данные страны.

Настройка нашей среды разработки

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

git clone [email protected]:Ugur22/recharts-basics.git
cd recharts-basics
npm install
npm start

В этом проекте мы собираемся использовать следующие инструменты для создания информационной панели Covid-19:

  • Recharts — библиотека диаграмм для построения графиков.
  • Moment.js — анализирует и отображает даты.
  • Bulma — CSS-фреймворк для стилей и сетки.
  • Sass CSS — простое повторное использование CSS и миксинов.

После того, как вы закончите, вы должны увидеть следующую диаграмму в своем веб-приложении:

Отлично, теперь, когда все готово, мы можем приступить к созданию приборной панели. В вашем App.jsx вы можете увидеть следующий код, который отображает вашу диаграмму. Как видите, Recharts требует очень мало кода для построения сложной диаграммы. Во-первых, мы импортируем необходимые компоненты, необходимые для нашей диаграммы. Поскольку в этом примере мы использовали линейный график, нам также нужно было импортировать линейный график и линейный график. Если вы хотите использовать, например, диаграмму с областями, вы можете заменить их на AreaChart и область. YAxis используется для отображения значений на графике, а XAxes — для их распределения по горизонтали. Позже мы будем использовать XAxes для отображения дат, чтобы вы могли видеть, какое значение возникает в какую дату. Компонент Tooltip дает вам всю всплывающую подсказку без дополнительного кода, когда вы наводите курсор на каждую точку данных. В элементе Line вы также можете увидеть свойство с именем dataKey. При этом вы можете выбрать, какое поле из ваших данных вы хотите отобразить на диаграмме. В этом случае вы можете видеть, что для первой строки отображается значение pv для каждой страницы, а для второй строки используется поле uv.

import { LineChart, Line, XAxis, YAxis, Tooltip, Legend} from "recharts";
const data = [
  { name: 'Page A', uv: 4000, pv: 2400, amt: 2400 },
  { name: 'Page B', uv: 3000, pv: 1398, amt: 2210 },
  { name: 'Page C', uv: 2000, pv: 9800, amt: 2290 },
  { name: 'Page D', uv: 2780, pv: 3908, amt: 2000 },
  { name: 'Page E', uv: 1890, pv: 4800, amt: 2181 },
  { name: 'Page F', uv: 2390, pv: 3800, amt: 2500 },
  { name: 'Page G', uv: 3490, pv: 4300, amt: 2100 },
];
function App() {
  return (
    <div className="App">
      <LineChart width={800} height={400} data={data}
        margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Line type="monotone" dataKey="pv" stroke="#8884d8" />
        <Line type="monotone" dataKey="uv" stroke="#82ca9d" />
      </LineChart>
    </div>
  );
}

Давайте попробуем изменить эту диаграмму, чтобы вы могли понять, как работает Recharts. Попробуйте заменить Line на Area и LineChart на AreaChart. Если вы сейчас посмотрите на свою диаграмму, вы должны увидеть те же данные, которые отображаются на диаграмме с областями.

Вы также можете немного поиграть с данными, изменив значения, чтобы увидеть, как это повлияет на диаграмму. Под диаграммой вы также можете увидеть легенду, которая отображается для каждого графика, который мы рисуем, представляющий имена наборов данных.

Теперь, когда у нас есть представление о том, как нарисовать диаграмму в Recharts, давайте воспользуемся ею для отображения диаграммы реальных данных API вместо данных макета. Как указано выше, для этого мы будем использовать API novovcovid19, чтобы отображать данные о Covid-19 для одной страны.

Чтобы получить данные из API, нам нужно сначала сохранить их в состоянии. Для этого мы будем использовать useState и useEffect из React, как показано ниже.

import React, { useState, useEffect } from 'react';
import { AreaChart, Area, XAxis, YAxis, Tooltip, Legend} from "recharts";
function App() {
  let [data, setData] = useState([]);
  useEffect(() => {
    fetchData();
  }, [])
  const fetchData = () => {
    fetch(`https://api.covid19api.com/total/country/Italy`)
      .then(response => response.json())
      .then(json => setData(json))
  }
// Added to filter out zero values form the API
data = data.filter(a => (a.Active !== 0 && a.Recovered !== 0 &          a.Deaths !== 0 ));
console.log(data);
return (
    <div className="App">
      <AreaChart width={800} height={400} data={data}
        margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Area type="monotone" dataKey="pv" stroke="#8884d8" />
      </AreaChart>
    </div>
  );
}

С помощью useEffect мы можем вызвать функцию FetchData(), которая, в свою очередь, выполнит вызов API через метод fetch. В моем случае я выбираю, но вы можете выбрать любую страну, которую вы предпочитаете. Используя SetData, мы можем хранить данные API в переменной data. Чтобы убедиться, что вызов API работает правильно, мы будем console.logданные. Если все сделано правильно, вы должны получить результат, аналогичный приведенному ниже.

Теперь вам, вероятно, интересно, почему ваша диаграмма ничего не показывает, хотя вы указали данные в AreaChart. Это связано с тем, что Recharts также необходимо знать, какие значения должны отображаться на XAxis и datakey для области, давайте сделаем это прямо сейчас.

Для XAxes мы можем добавить дату как adatakey, а в Area мы добавим значение для отображения случаев Covid-19. В выводе выше вы можете увидеть, какие значения мы можем выбрать. Вы можете выбрать то, что вам нравится. Например, если я выбираю «Активный», я получаю все активные дела за день на своем графике, как показано ниже.

<Area type="monotone" dataKey="Active" stroke="#8884d8"

Если все сделано правильно, вы должны увидеть диаграмму, похожую на приведенную выше, показывающую случаи Covid-19. Одна вещь, которую мы замечаем, это то, что дата еще не отформатирована правильно по осям X. Это можно исправить с помощью moment.js, так что давайте сделаем это быстро. поэтому давайте импортируем moment.js, а затем используем moment для форматирования даты в желаемом формате.

import moment from 'moment';

Для этого мы создадим функцию CustomizedAxisTick. Вы можете заглянуть на сайт moment.js, чтобы найти формат, который вам больше нравится. Я выбираю формат ll, потому что мне нравится сокращенное обозначение месяца с днем. После форматирования я использую slice, чтобы отрезать год, так как в этом примере он нам не нужен.

const CustomizedAxisTick = ({ x, y, payload }) => {
 const dateTip = moment(payload.value)
   .format("ll")
   .slice(0, 6);
    return (
   <g transform={`translate(${x},${y})`}>
  <text x={23} y={0} dy={14} fontSize="0.90em" fontFamily="bold" textAnchor="end" fill="#363636">
    {dateTip}</text>
   </g>
  );
 }

После создания этой функции вы можете добавить еще одно свойство к XAxes под названием tick и добавить к нему нашу новую функцию следующим образом:

<XAxis dataKey="Date" tick={CustomizedAxisTick}  />

После добавления этого ваша диаграмма должна правильно отображать даты, как показано ниже. Я также изменил цвет на оранжевый, потому что он больше подходит для активных случаев, чем синий цвет.

<Area type="monotone" dataKey="Active" fill="#e67e22"

Отлично, теперь у нас есть рабочая диаграмма, показывающая реальные данные из API. Вы можете немного поиграть с этим, изменив datakey для области, чтобы увидеть, как это влияет на график. Итак, теперь, когда у нас есть ваша первая рабочая диаграмма, давайте добавим к ней немного интерактивности.

Итак, давайте сначала добавим функцию для настройки стиля и форматирования всплывающей подсказки.

const CustomTooltip = ({ active, payload, label }) => {
 const dateTip = moment(label)
   .format("llll")
   .slice(0, 12);
 const formattedDate = dateTip
 if (payload === null) return
 if (active)
   return (
  <div className="custom-tooltip">
    <p className="label-tooltip">{`${formattedDate}`}</p>
    <p className="desc-tooltip">
   <span className="value-tooltip">Total Cases: {payload[0].value.toLocaleString()}</span>
    </p>
  </div>
   );
 return null;
};

Кроме того, вам также нужно будет добавить этот стиль к style.scss , чтобы придать всплывающей подсказке чистый вид.

.custom-tooltip {
  padding: 10px;
  background-color: rgba(255, 255, 255, 0.7);
  border: 2px solid #c3c3c3;
  border-radius: 10px;
  span {
    font-weight: bold;
  }
}

Теперь мы можем добавить функцию CustomTooltip во всплывающую подсказку следующим образом. Вы также можете добавить свойство animationDuration, чтобы изменить задержку всплывающей подсказки при наведении курсора на другое значение. Я установил свой на ноль, чтобы не было задержки.

<Tooltip content={<CustomTooltip />} animationDuration={0} />

Теперь для большей интерактивности мы также добавим компонент кисти. Этот компонент позволяет пользователю выбирать только определенный диапазон данных с помощью ползунка. Чтобы добавить это, нам сначала нужно добавить еще одну пользовательскую функцию для правильного форматирования даты. Несмотря на то, что мы форматируем ту же дату, что и для всплывающей подсказки, нам нужно создать другую, потому что компонент «Кисть» не принимает элементы HTML, которые возвращаются в функции CustomizedAxisTick.

const xAxisTickFormatter = (timestamp_measured) => {
 return moment(timestamp_measured)
   .format("ll")
   .slice(0, 6);
  }

Теперь давайте добавим компонент кисти на нашу диаграмму. Вы можете поместить его в AreaChart.

<AreaChart width={800} height={400} data={data}
   margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
   <XAxis dataKey="Date" tick={CustomizedAxisTick}  />
   <YAxis />
   <Tooltip content={<CustomTooltip />} animationDuration={0}/>
   <Legend />
   <Area type="monotone" dataKey="Active" fill="#e67e22"
   stroke="#e67e22" />             
   <Brush tickFormatter={xAxisTickFormatter} dataKey="Date" />
 </AreaChart>

После правильного добавления всплывающей подсказки и кисти ваша диаграмма должна работать, как показано ниже.

Ваша диаграмма теперь намного интереснее, потому что кисть позволяет пользователю увеличить определенный диапазон дат, чтобы сделать новые наблюдения. Рядом с этим обновленная всплывающая подсказка теперь дает вам количество дел, привязанных к дате, чтобы сделать более очевидным для пользователя, к какой дате относится количество дел. Чтобы у нас была полностью рабочая диаграмма с некоторой интерактивностью, давайте попробуем создать дашборд. Сначала мы хотим создать три столбца над диаграммами, показывающими цифры Covid-19 для каждого типа случая (активный, выздоровевший и умерший).

Давайте сначала получим последнее значение каждого типа дела. мы можем использовать для этого оператор распространения с Math.max для каждого значения, как показано ниже. кроме того, мы также можем получить название страны с помощью data.map и разделить его на 1, чтобы получить только одно значение.

const amount_Active = data.map((a) => a.Active);
 let latest_Active = Math.max(...amount_Active);
const amount_deaths = data.map((a) => a.Deaths);
 let latest_deaths = Math.max(...amount_deaths);
const amount_recovered = data.map((a) => a.Recovered);
 let latest_recovered = Math.max(...amount_recovered);
const getCountries = data.map((a) => a.Country);
 country = getCountries.slice(0, 1);

Если вы console.log() это, вы должны получить последние значения для каждого типа случая и названия страны из API Covid-19. Затем нам также нужно добавить переменные useState, чтобы мы могли сообщить реакции, какая кнопка нажата и какой стиль она должна получить соответственно.

const orange = '#e67e22';
const red = '#e74c3c';
const green = '#27ae60';
let [color, setColor] = useState(orange);
let [activeIndex, setActive] = useState(0);
let country;

Теперь мы можем настроить наш массив BUTTONS.

const BUTTONS = [
  {
   name: "Active",
   color: orange,
   value: latest_Active,
   id: 1
  },
  {
   name: "Deaths",
   color: red,
   value: latest_deaths,
   id: 2
  },
  {
   name: "Recovered",
   color: green,
   value: latest_recovered,
   id: 3
  },
 ]

После добавления этого мы можем использовать этот массив для циклического обхода этого массива в нашем HTML.

<div className="dashboard">
   <h1 className="title is-3">{country} Covid-19 cases</h1>
   <div className="columns dashboard__numbers">
    {BUTTONS.map((item, index) =>
     <div className="column" key={index} >
      <h2>
       <button style={{ color: item.color === color ? color : "#000" }} onClick={() => [setType(item.name), setActive(index),
       setColor(item.color)]} className={activeIndex === index ? 'column__button title is-3 selected' : 'column__button title is-3'}>
        {item.name}
       </button>
      </h2>
      <p className="subtitle is-4" >{item.value.toLocaleString()}</p>
     </div>
    )}
   </div>
   <div className="columns">
    <AreaChart width={800} height={400} data={data}
     margin={{ top: 5, right: 30, left: 20, bottom: 5 }}>
     <XAxis dataKey="Date" tick={CustomizedAxisTick} />
     <YAxis />
     <Tooltip content={<CustomTooltip />} animationDuration={0} />
     <Legend />
     <Area type="monotone" dataKey={type} fill={color} stroke={color} />
     <Brush tickFormatter={xAxisTickFormatter} startIndex={Math.round(data.length * 0.45)} />
    </AreaChart>
   </div>
  </div>

также измените приложение className на панель инструментов и добавьте dashboard.scss как импорт в style.scss и удалите стиль для класса .App. Взгляните на dashboard.scss и увидите, что я уже добавил стили для столбцов и диаграмм. Я сделал его, чтобы мы могли сосредоточиться в первую очередь на Recharts.

@import 'dashboard';

Теперь ваша панель инструментов должна выглядеть так, как показано ниже, где показаны последние данные для каждого типа дела.

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

<button style={{ color: item.color === color ? color : "#000" }} onClick={() => [setType(item.name), setActive(index),

Далее мы хотим изменить данные диаграммы, выбрав конкретный тип случая, нажав кнопку. Вы можете видеть, что мы уже добавили setType к onClick на кнопке, которая сохраняет значение в переменной типа. Итак, все, что нам нужно сделать сейчас, это добавить это значение к AreaChart.

Теперь мы можем легко добавить переменную типа к свойству datakey вместо строки. кроме того, мы также можем добавить цвет к значению заливки и обводки, чтобы сделать цвет диаграммы динамичным.

<Area type="monotone" dataKey={type} fill={color} stroke={color} />

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

Чтобы не усложнять этот урок, мы закончим его здесь и вместо этого дадим вам домашнее задание по улучшению этой панели. Прежде всего, вы можете попробовать добавить несколько диаграмм рядом с существующей, чтобы создать настоящую информационную панель. Попробуйте поэкспериментировать с различными типами диаграмм, такими как гистограммы, линейные диаграммы и круговые диаграммы. Вы можете добавить эти диаграммы так же, как мы добавили AreaChart. Помимо этого, вы также можете добавить раскрывающееся меню, которое позволяет пользователю переключаться между странами. Для этого вам нужно будет добавить параметр к вызову API, чтобы сделать его динамическим. Это будет выглядеть примерно так.

https://api.covid19api.com/total/country/${country}`

Если вам нужно вдохновение в том, как улучшить свою панель инструментов, вы можете взглянуть на мой, который я создал для этого урока в качестве примера.

Ресурсы, использованные в этой статье…