Построение графика Radar Chart.js

Есть массив данных

            [88.331566, 161.26106],
            [267.78873, 69.070625],
            [61.81063, 200.0],
            [54.48104, 200.0],
            [48.937656, 200.0],
            [139.215, 70.5277],
            [105.86972, 234.48161],
            [111.62624, 220.65602],
            [12.477702, 197.3125],
            [40.90647, 146.83994],
            [39.692104, 147.6453],
            [11.931946, 91.9375],
            [112.736885, 147.54906],

По ним нужно построить график такого вида:График

Первое значение в массиве угол (градус). Второе, расстояние от центра графика. Пытаюсь это реализовать с помощью Chart.js, но можно любым другим способом. График со скриншота был построен так:

labels: [
    0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130,
    140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250,
    260, 270, 280, 290, 300, 310, 320, 330, 340, 350,
],
datasets: [
    {
        label: "Test",
        backgroundColor: "rgba(179,181,198,0.2)",
        borderColor: "rgba(179,181,198,1)",
        pointBackgroundColor: "rgba(179,181,198,1)",
        pointBorderColor: "#fff",
        pointHoverBackgroundColor: "#fff",
        pointHoverBorderColor: "rgba(179,181,198,1)",
        data: [
            0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130,
            140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250,
            260, 270, 280, 290, 300, 310, 320, 330, 340, 350
        ],
     },
 ],

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

Визуальный пример того, что должно получится Пример того что должно получится


Ответы (1 шт):

Автор решения: Dev18

У нас есть массив data, в котором хранятся пары значений [angle, distance] Здесь angle — это угол в градусах, а distance — расстояние от центра графика

Мы преобразуем каждую пару [angle, distance] в объект с ключами r и theta, где r — это расстояние, а theta — угол. Это делается с помощью метода map

Затем создаем массив labels, содержащий метки для каждого угла от 0 до 359 градусов. Эти метки будут отображаться по окружности графика как в вашем примере

Массив distances заполняется значениями null длиной 360 элементов. В этот массив будут записываться значения расстояний для соответствующих углов

Для каждого угла, который указан в массиве points, мы записываем соответствующее значение расстояния в массив distances. Если несколько точек имеют один и тот же угол, будет учитываться только последнее значение

Далее массив dataset, который будет содержать расстояния для каждого угла от 0 до 359 градусов. Если для какого-то угла нет расстояния (т.е. distances[i] равно null), будет установлено значениее 0

Сгенерируем разноцветные точки pointColors

адаптивность надо доработать

Пример графика radar пар значений угол-расстояние с использованием библиотеки Chart.js

const data = [
  [88.331566, 161.26106],
  [267.78873, 69.070625],
  [61.81063, 200.0],
  [54.48104, 200.0],
  [48.937656, 200.0],
  [139.215, 70.5277],
  [105.86972, 234.48161],
  [111.62624, 220.65602],
  [12.477702, 197.3125],
  [40.90647, 146.83994],
  [39.692104, 147.6453],
  [11.931946, 91.9375],
  [112.736885, 147.54906],
];

// Преобразование данных в точки с углом и расстоянием
const points = data.map(([angle, distance]) => ({
  r: distance, // расстояние от центра
  theta: angle // угол в градусах
}));

// Создание меток для каждого угла от 0 до 359 градусов
const labels = Array.from({
  length: 360
}, (_, i) => i);

// Создание массива для расстояний, инициализированного значениями null
const distances = new Array(360).fill(null);

// Заполнение массива distances значениями расстояний на соответствующих углах
points.forEach(point => {
  distances[Math.round(point.theta)] = point.r;
});

// Создание финального набора данных, где для каждого угла есть соответствующее расстояние
const dataset = labels.map((label, i) => distances[i] || 0);

// Генерация случайных цветов для каждой точки на графике
const pointColors = dataset.map(() => `hsl(${Math.random() * 360}, 100%, 50%)`);

// Настройка и отрисовка графика radar с использованием Chart.js
const ctx = document.getElementById('myRadarChart').getContext('2d');
const myRadarChart = new Chart(ctx, {
  type: 'radar',
  data: {
    labels: labels, // Угловые метки
    datasets: [{
      label: 'Distance from center', // Подпись набора данных
      data: dataset, // Расстояния для каждого угла
      backgroundColor: 'rgba(54, 162, 235, 0)', // Прозрачный фон для набора данных
      borderColor: 'rgba(54, 162, 235, 0)', // Прозрачный цвет линий (линии скрыты)
      pointBackgroundColor: pointColors, // Цвета точек на графике
      pointBorderColor: '#fff', // Цвет обводки точек
      pointHoverBackgroundColor: pointColors, // Цвета точек при наведении
      pointHoverBorderColor: 'rgba(54, 162, 235, 1)', // Цвет обводки точек при наведении
      pointRadius: 5, // Размер точек
      borderWidth: 0, // Толщина линий (линии скрыты)
      fill: false // Отключаем заливку области под графиком
    }]
  },
  options: {
    scales: {
      r: {
        angleLines: {
          display: true // Отображение линий для каждого угла
        },
        ticks: {
          display: true, // Отображение меток на круговой шкале
          suggestedMin: 0, // Минимальное значение шкалы
          suggestedMax: Math.max(...dataset) // Максимальное значение шкалы
        },
        pointLabels: {
          fontSize: 10, // Размер шрифта угловых меток
          callback: function(value, index) {
            // Отображение метки только на каждом 10-м значении
            return index % 10 === 0 ? value : '';
          }
        }
      }
    },
    plugins: {
      legend: {
        display: true, // Отображение легенды
        position: 'top' // Позиция легенды сверху
      }
    }
  }
});
body {
  font-family: Arial, sans-serif;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  background-color: #f4f4f4;
}

canvas {
  max-width: 80%;
  max-height: 80%;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Radar Chart Example</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

</head>

<body>

  <canvas id="myRadarChart"></canvas>



</body>

</html>

→ Ссылка