L'implémentation de tableaux de bord interactifs nécessite souvent la visualisation de données sous plusieurs angles. Cet article présente une solution technique pour afficher simultanément un histogramme (ou graphique linéaire) et un diagramme circulaire sur une seule page, alimentés par une source de données unique. La solution inclut une gestion dynamique des thèmes, un filtrage par période pour le diagramme circulaire et une adaptation responsive de l'interface.
Structure HTML et Dépendances
Pour commencer, nous définissons l'espace de rendu pour les graphiques et les contrôles utilisateur (sélection de mois et changement de thème graphique).
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Visualisation de Données Import-Export</title>
<!-- Chargement des bibliothèques via CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.3/echarts.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div style="padding: 20px; text-align: center;">
<label>Style visuel : </label>
<select id="themeSelector">
<option value="vintage">Vintage</option>
<option value="dark">Dark</option>
<option value="macarons">Macarons</option>
<option value="infographic">Infographic</option>
</select>
<label style="margin-left: 20px;">Période : </label>
<select id="monthSelector"></select>
</div>
<div style="display: flex; flex-wrap: wrap; justify-content: space-around;">
<div id="barChartContainer" style="width: 55%; height: 500px;"></div>
<div id="pieChartContainer" style="width: 40%; height: 500px;"></div>
</div>
<script src="app.js"></script>
</body>
</html>
Logique de Traitement des Données et Initialisation
Le script JavaScript suivant gère l'extraction des données, le formatage pour ECharts et la synchronisation des composants. L'histogramme affiche l'évolution globale, tandis que le diagramme circulaire se concentre sur la répartition d'un mois spécifique.
let barChart, pieChart;
let globalData = {}; // Stockage des données reçues de l'API
const initDashboard = () => {
barChart = echarts.init(document.getElementById('barChartContainer'), 'vintage');
pieChart = echarts.init(document.getElementById('pieChartContainer'), 'vintage');
// Simulation d'appel API
fetchData();
};
const fetchData = () => {
// Structure type du JSON : {"2023-01": {"imports": 120, "exports": 80}, ...}
const mockData = {
"2023-01": { imports: 1500, exports: 1200 },
"2023-02": { imports: 1800, exports: 1100 },
"2023-03": { imports: 1400, exports: 1600 },
"2023-04": { imports: 2100, exports: 1900 }
};
globalData = mockData;
renderCharts(mockData);
};
const renderCharts = (data) => {
const months = Object.keys(data);
const importValues = months.map(m => data[m].imports);
const exportValues = months.map(m => data[m].exports);
// Remplissage du sélecteur de mois
const selector = $('#monthSelector');
selector.empty();
months.forEach((m, index) => {
const selected = (index === months.length - 1) ? 'selected' : '';
selector.append(`<option value="${m}" ${selected}>${m}</option>`);
});
updateBarChart(months, importValues, exportValues);
updatePieChart(months[months.length - 1]);
};
function updateBarChart(labels, imports, exports) {
const option = {
title: { text: 'Bilan Annuel Import/Export', left: 'center' },
tooltip: { trigger: 'axis' },
legend: { show: false }, // Légende masquée selon spécifications
toolbox: {
feature: {
magicType: { type: ['line', 'bar'] },
saveAsImage: {},
dataView: {}
}
},
xAxis: { type: 'category', data: labels },
yAxis: { type: 'value', name: 'Tonnes' },
series: [
{ name: 'Importations', type: 'bar', data: imports },
{ name: 'Exportations', type: 'bar', data: exports }
]
};
barChart.setOption(option);
}
function updatePieChart(selectedMonth) {
const monthData = globalData[selectedMonth];
const option = {
title: { text: `Répartition : ${selectedMonth}`, left: 'center' },
tooltip: { trigger: 'item', formatter: '{b} : {c} ({d}%)' },
toolbox: { feature: { saveAsImage: {} } },
series: [{
type: 'pie',
radius: '60%',
data: [
{ value: monthData.imports, name: 'Importations' },
{ value: monthData.exports, name: 'Exportations' }
]
}]
};
pieChart.setOption(option);
}
// Gestion des événements
$('#monthSelector').on('change', function() {
updatePieChart($(this).val());
});
$('#themeSelector').on('change', function() {
const selectedTheme = $(this).val();
// Destruction et réinitialisation pour appliquer le thème
const barOpt = barChart.getOption();
const pieOpt = pieChart.getOption();
barChart.dispose();
pieChart.dispose();
barChart = echarts.init(document.getElementById('barChartContainer'), selectedTheme);
pieChart = echarts.init(document.getElementById('pieChartContainer'), selectedTheme);
barChart.setOption(barOpt);
pieChart.setOption(pieOpt);
});
window.addEventListener('resize', () => {
barChart && barChart.resize();
pieChart && pieChart.resize();
});
$(document).ready(initDashboard);
Fonctionnalités Clés
- Source de données unique : Le traitement AJAX ne récupère qu'un seul objet JSON. Les données sont ensuite segmentées localement pour alimenter les différents types de graphiques, réduisant ainsi la charge réseau.
- Interactivité croisée : Le menu déroulant des mois permet de mettre à jour le
pieChartsans recalculer l'intégralité de l'ihstogramme, offrant une expérience utilisateur fluide. - Gestion dynamique des thèmes : L'utilisation de
dispose()permet de reconstruire les instances ECharts avec de nouveaux schémas de couleurs à la volée tout en conservant les données actuelles viagetOption(). - Outils intégrés : Chaque conteneur possède sa propre
toolbox, permettant l'exportation d'images ou le basculement entre vues (courbe/barre) de manière isolée.