216 lines
9.1 KiB
HTML
216 lines
9.1 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Тест Box and Whisker диаграммы AnyChart</title>
|
||
<script src="https://cdn.anychart.com/releases/v8/js/anychart-base.min.js"></script>
|
||
<script src="https://cdn.anychart.com/releases/v8/js/anychart-ui.min.js"></script>
|
||
<script src="https://cdn.anychart.com/releases/v8/js/anychart-exports.min.js"></script>
|
||
<script src="https://cdn.anychart.com/releases/v8/js/anychart-data-adapter.min.js"></script>
|
||
<link rel="stylesheet" href="https://cdn.anychart.com/releases/v8/css/anychart-ui.min.css">
|
||
<link rel="stylesheet" href="https://cdn.anychart.com/releases/v8/fonts/css/anychart-font.min.css">
|
||
<style>
|
||
body {
|
||
font-family: Arial, sans-serif;
|
||
background: linear-gradient(to right, #9da8f9, #fce7ff);
|
||
margin: 0;
|
||
padding: 20px;
|
||
}
|
||
.container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
background: white;
|
||
border-radius: 12px;
|
||
padding: 20px;
|
||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||
}
|
||
#chart-container {
|
||
height: 500px;
|
||
margin: 20px 0;
|
||
}
|
||
.legend {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 20px;
|
||
margin-top: 20px;
|
||
font-size: 14px;
|
||
}
|
||
.legend-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.legend-box {
|
||
width: 16px;
|
||
height: 12px;
|
||
border: 1px solid;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h1>Тест Box and Whisker диаграммы - Сравнение позиций товаров</h1>
|
||
<p>Тестируем Box and Whisker диаграмму с исправлением для одинаковых позиций</p>
|
||
|
||
<div id="chart-container"></div>
|
||
|
||
<div class="legend">
|
||
<div class="legend-item">
|
||
<div class="legend-box" style="background-color: rgba(34, 197, 94, 0.3); border-color: #22c55e;"></div>
|
||
<span>Диапазон позиций</span>
|
||
</div>
|
||
<div class="legend-item">
|
||
<div class="legend-box" style="background-color: #16a34a; border-color: #16a34a; height: 3px;"></div>
|
||
<span>Медиана</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
anychart.onDocumentReady(function () {
|
||
// Тестовые данные позиций
|
||
const testData = [
|
||
{ city: 'Москва', myPosition: 5, competitorPosition: 3 },
|
||
{ city: 'СПб', myPosition: 2, competitorPosition: 7 },
|
||
{ city: 'Екатеринбург', myPosition: 1, competitorPosition: 1 }, // Одинаковые позиции
|
||
{ city: 'Новосибирск', myPosition: 8, competitorPosition: 4 },
|
||
{ city: 'Казань', myPosition: 3, competitorPosition: 12 }
|
||
];
|
||
|
||
// Преобразуем данные для Box and Whisker диаграммы с исправлением одинаковых значений
|
||
function prepareBoxData(data) {
|
||
return data.map((item) => {
|
||
// Собираем все позиции (исключаем нулевые и отрицательные)
|
||
const positions = [item.myPosition, item.competitorPosition].filter(p => p > 0);
|
||
|
||
if (positions.length === 0) {
|
||
// Если нет валидных позиций, создаем базовый элемент
|
||
return {
|
||
x: item.city,
|
||
low: 1,
|
||
q1: 1,
|
||
median: 1,
|
||
q3: 1,
|
||
high: 1,
|
||
outliers: []
|
||
};
|
||
}
|
||
|
||
if (positions.length === 1) {
|
||
// Если только одна позиция, показываем её как точку
|
||
const pos = positions[0];
|
||
return {
|
||
x: item.city,
|
||
low: pos,
|
||
q1: pos,
|
||
median: pos,
|
||
q3: pos,
|
||
high: pos,
|
||
outliers: []
|
||
};
|
||
}
|
||
|
||
// Если две позиции
|
||
let [pos1, pos2] = positions;
|
||
|
||
// Если позиции одинаковые, добавляем небольшое смещение для визуализации
|
||
if (pos1 === pos2) {
|
||
pos2 = pos1 + 0.1; // Небольшое смещение
|
||
}
|
||
|
||
const min = Math.min(pos1, pos2);
|
||
const max = Math.max(pos1, pos2);
|
||
const median = (pos1 + pos2) / 2;
|
||
|
||
return {
|
||
x: item.city,
|
||
low: min,
|
||
q1: min,
|
||
median: median,
|
||
q3: max,
|
||
high: max,
|
||
outliers: []
|
||
};
|
||
});
|
||
}
|
||
|
||
try {
|
||
// Подготавливаем данные
|
||
const boxData = prepareBoxData(testData);
|
||
console.log('Данные для диаграммы:', boxData);
|
||
|
||
// Создаем Box and Whisker диаграмму
|
||
const chart = anychart.box();
|
||
|
||
// Настраиваем заголовок
|
||
chart.title('Сравнение позиций товаров по городам');
|
||
chart.title().fontColor('#22c55e');
|
||
chart.title().fontSize(18);
|
||
|
||
// Настраиваем оси
|
||
chart.yAxis().title('Позиция');
|
||
chart.yAxis().labels().format('{%value}');
|
||
|
||
chart.xAxis().title('Города');
|
||
chart.xAxis().staggerMode(true);
|
||
|
||
// Инвертируем ось Y (позиция 1 сверху)
|
||
try {
|
||
chart.yScale().inverted(true);
|
||
} catch (error) {
|
||
console.log('Не удалось инвертировать ось Y:', error);
|
||
}
|
||
|
||
// Создаем серию
|
||
const series = chart.box(boxData);
|
||
|
||
// Настраиваем внешний вид
|
||
series.whiskerWidth('60%');
|
||
series.fill('#22c55e', 0.3);
|
||
series.stroke('#22c55e', 2);
|
||
series.whiskerStroke('#22c55e', 2);
|
||
series.medianStroke('#16a34a', 3);
|
||
|
||
// Настраиваем подсказки
|
||
series.tooltip().format(
|
||
'Город: {%x}' +
|
||
'\nМин позиция: {%low}' +
|
||
'\nМакс позиция: {%high}' +
|
||
'\nМедиана: {%median}'
|
||
);
|
||
|
||
// Настраиваем сетку
|
||
try {
|
||
chart.grid(0).stroke('#e5e7eb', 1, '2 2');
|
||
chart.grid(1).layout('vertical').stroke('#e5e7eb', 1, '2 2');
|
||
} catch (error) {
|
||
console.log('Не удалось настроить сетку:', error);
|
||
try {
|
||
chart.yGrid(true);
|
||
chart.xGrid(true);
|
||
} catch (gridError) {
|
||
console.log('Альтернативная настройка сетки также недоступна:', gridError);
|
||
}
|
||
}
|
||
|
||
// Настраиваем фон
|
||
chart.background().fill('transparent');
|
||
|
||
// Устанавливаем контейнер и отрисовываем
|
||
chart.container('chart-container');
|
||
chart.draw();
|
||
|
||
console.log('Диаграмма успешно создана!');
|
||
|
||
} catch (error) {
|
||
console.error('Ошибка при создании диаграммы:', error);
|
||
document.getElementById('chart-container').innerHTML =
|
||
'<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #ef4444;">' +
|
||
'<div><h3>Ошибка загрузки диаграммы</h3><p>' + error.message + '</p></div>' +
|
||
'</div>';
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |