Intégration de Graphiques Mixtes avec ECharts : Histogramme et Diagramme Circulaire Synchronisés

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 pieChart sans 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 via getOption().
  • 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.

Étiquettes: ECharts JavaScript Data-Visualization Front-end web-development

Publié le 15 juillet à 05h58