Построение графика 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 шт):
У нас есть массив 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>