Faire un graphique en ligne (Line Chart) dans Flutter


Avatar de Pierre Courtois

Maintenant que nous avons implémenté syncfusion_flutter_charts, voyons comment faire notre premier graphique, avec un Line Chart, ou Graphique en ligne en français.


À quoi sert un graphique en lignes ?

Les graphiques en lignes sont idéaux pour visualiser des tendances continues ou des évolutions dans le temps. Ils permettent de suivre des données qui changent progressivement, comme des températures quotidiennes, des ventes mensuelles, ou des performances sportives sur une saison. Ils sont simples à comprendre, ce qui en fait des outils parfaits pour :

  • Montrer des progressions ou des régressions (ex. : revenus annuels).
  • Comparer plusieurs séries de données sur un même axe (ex. : températures de plusieurs villes).
  • Identifier des pics ou des creux dans des données continues (ex. : trafic réseau).

Créer un Line Chart de base

Voici un exemple simple pour afficher des données de ventes annuelles.

Assurez-vous au préalable de bien avoir mis en place syncfusion_flutter_charts en ajoutant sa dépendance dans votre fichier pubspec.yaml.

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Column Chart de base')),
        body: Center(
          child: SfCartesianChart(
            primaryXAxis: CategoryAxis(),
            series: <ColumnSeries<SalesData, String>>[
              ColumnSeries<SalesData, String>(
                dataSource: [
                  SalesData('Jan', 35),
                  SalesData('Fév', 28),
                  SalesData('Mar', 34),
                  SalesData('Avr', 32),
                  SalesData('Mai', 40),
                ],
                xValueMapper: (SalesData sales, _) => sales.month,
                yValueMapper: (SalesData sales, _) => sales.sales,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class SalesData {
  SalesData(this.month, this.sales);
  final String month;
  final double sales;
}

Voici les éléments qui sont indispensables pour faire un graphique en ligne simple dans Flutter :

  • SfCartesianChart : Le conteneur principal pour tout graphique cartésien (lignes, barres, etc.).
  • primaryXAxis : Définit l’axe horizontal. Sans ça, le graphique ne sait pas comment interpréter les données X.
  • series : La liste des séries à afficher. Sans série, il n’y a rien à dessiner.
  • LineSeries : Spécifie qu’on veut un graphique en lignes.
  • dataSource : Les données brutes (liste d’objets).
  • xValueMapper et yValueMapper : Relient les données aux axes X et Y.

Pourquoi créer une classe SalesData ?

Cette classe n’est pas un widget, mais elle structure les données. Vous pourriez utiliser une simple liste de maps (ex. : {‘year’: 2020, ‘sales’: 35}), mais une classe rend le code plus clair.

Comment ajouter plusieurs lignes au graphique ?

Un graphique en lignes devient encore plus puissant quand il affiche plusieurs séries de données pour comparer des tendances. Avec syncfusion_flutter_charts, il suffit d’ajouter plusieurs LineSeries à la liste series de SfCartesianChart. Chaque série peut avoir ses propres données, couleurs, marqueurs et légendes. Voici comment faire.

Voici un exemple ou ma classe SalesData contient deux liste de données à présenter :

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  final TooltipBehavior _tooltip = TooltipBehavior(enable: true);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Line Chart avec plusieurs lignes')),
        body: SfCartesianChart(
          title: ChartTitle(text: 'Ventes par région (2025)'),
          legend: Legend(isVisible: true), // Active la légende pour identifier les lignes
          tooltipBehavior: _tooltip,
          primaryXAxis: CategoryAxis(
            title: AxisTitle(text: 'Mois'),
          ),
          primaryYAxis: NumericAxis(
            title: AxisTitle(text: 'Ventes (k€)'),
            minimum: 20,
            maximum: 50,
          ),
          series: <LineSeries<SalesData, String>>[
            // Première ligne : Région A
            LineSeries<SalesData, String>(
              name: 'Région A', // Nom pour la légende
              dataSource: [
                SalesData('Jan', 35),
                SalesData('Fév', 28),
                SalesData('Mar', 34),
                SalesData('Avr', 32),
                SalesData('Mai', 40),
              ],
              xValueMapper: (SalesData sales, _) => sales.month,
              yValueMapper: (SalesData sales, _) => sales.sales,
              color: Colors.blue, // Couleur de la ligne
              markerSettings: MarkerSettings(
                isVisible: true,
                shape: DataMarkerType.circle,
                width: 6,
                height: 6,
                color: Colors.blue,
              ),
            ),
            // Deuxième ligne : Région B
            LineSeries<SalesData, String>(
              name: 'Région B', // Nom pour la légende
              dataSource: [
                SalesData('Jan', 25),
                SalesData('Fév', 30),
                SalesData('Mar', 27),
                SalesData('Avr', 35),
                SalesData('Mai', 38),
              ],
              xValueMapper: (SalesData sales, _) => sales.month,
              yValueMapper: (SalesData sales, _) => sales.sales,
              color: Colors.red, // Couleur différente pour distinction
              markerSettings: MarkerSettings(
                isVisible: true,
                shape: DataMarkerType.triangle,
                width: 6,
                height: 6,
                color: Colors.red,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class SalesData {
  SalesData(this.month, this.sales);
  final String month;
  final double sales;
}

Si vos séries ont des échelles très différentes (ex. : une en milliers, l’autre en unités), vous pouvez ajouter deuxième axe Y supplémentaire.

Comment personnaliser votre graphique en ligne ?

Savoir faire un graphique en ligne dans Flutter est déjà un bon début, mais voyons maintenant comment le personnaliser selon vos besoins.

Changer l’apparence de la ligne

Vous pouvez modifier la couleur, l’épaisseur et la transparence de la ligne, en modifiant les propriétés suivantes :

  • color : Définit la couleur de la ligne.
  • width : Ajuste l’épaisseur.
  • opacity : Contrôle la transparence de la ligne (valeur entre 0 et 1).
LineSeries<SalesData, double>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.year,
  yValueMapper: (SalesData sales, _) => sales.sales,
  color: Colors.blueAccent, //Ligne de couleur bleu
  width: 3.0, //Épaisseur de 3 pixels
  opacity: 0.8, //Légèrement transparente
),

Faire une ligne en pointillés (Dashed line)

Utilisez dashArray pour créer une ligne en pointillés. Les valeurs alternent entre longueur des segments et espaces (ex. : [5, 5] = 5 unités pleines, 5 unités vides).

LineSeries<SalesData, double>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.year,
  yValueMapper: (SalesData sales, _) => sales.sales,
  dashArray: [5, 5], // Pointillés réguliers
),

Faire une ligne multicolore

Avec pointColorMapper, chaque segment peut avoir une couleur différente basée sur vos données.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Gráfico Syncfusion')),
        body: Center(
          child: SfCartesianChart(
            primaryXAxis: CategoryAxis(),
            title: ChartTitle(text: 'Ventas mensuales 2025'),
            series: <CartesianSeries>[
              LineSeries<SalesData, String>(
                  dataSource: [
                    SalesData('Jan', 35, Colors.red),
                    SalesData('Feb', 28, Colors.green),
                    SalesData('Mar', 34, Colors.blue),
                    SalesData('Apr', 32, Colors.yellow),
                    SalesData('May', 40, Colors.black)
                  ],
                  pointColorMapper: (SalesData data, _) => data.color,
                  xValueMapper: (SalesData data, _) => data.year,
                  yValueMapper: (SalesData data, _) => data.sales)
            ],
          ),
        ),
      ),
    );
  }
}

class SalesData {
  SalesData(this.year, this.sales, this.color);
  final String year;
  final double sales;
  final Color color;
}

La couleur s’applique sur le lien entre le point que vous avez défini et le point suivant. Par exemple si vous mettez votre premier point en rouge, c’est la ligne entre celui-ci et le deuxième point qui sera rouge.

Ajouter des marqueurs sur les points

Les markerSettings permettent d’afficher des marqueurs (cercles, carrés, etc.) sur chaque point de données :

  • isVisible : Active les marqueurs.
  • shape : Forme (cercle, rectangle, diamant, etc.).
  • size : Taille du marqueur.
  • color : Couleur.
//Affiche des points rouges
LineSeries<SalesData, double>(
  dataSource: /* ... */,
  markerSettings: MarkerSettings(
    isVisible: true,
    shape: DataMarkerType.circle,
    width: 6,
    height: 6,
    color: Colors.red,
  ),
  xValueMapper: (SalesData sales, _) => sales.year,
  yValueMapper: (SalesData sales, _) => sales.sales,
),

Voici la liste des différents marqueurs disponibles :

  • DataMarkerType.circle : Un marqueur rond classique.
  • DataMarkerType.rectangle : Un marqueur carré ou rectangulaire selon les valeurs de width et height.
  • DataMarkerType.triangle : Un marqueur en forme de triangle pointant vers le haut.
  • DataMarkerType.invertedTriangle : Un triangle pointant vers le bas.
  • DataMarkerType.diamond : Un marqueur en forme de losange.
  • DataMarkerType.pentagon : Un marqueur à cinq côtés.
  • DataMarkerType.verticalLine : Une petite ligne verticale centrée sur le point.
  • DataMarkerType.horizontalLine : Une petite ligne horizontale centrée sur le point.

Afficher des étiquettes de données

Avec dataLabelSettings, ajoutez des valeurs directement sur le graphique :

  • isVisible : Active les étiquettes.
  • labelAlignment : Position (au-dessus, en dessous, etc.).
  • textStyle : Style du texte.
LineSeries<SalesData, double>(
  dataSource: /* ... */,
  dataLabelSettings: DataLabelSettings(
    isVisible: true,
    labelAlignment: ChartDataLabelAlignment.top,
    textStyle: TextStyle(fontSize: 12, color: Colors.black),
  ),
  xValueMapper: (SalesData sales, _) => sales.year,
  yValueMapper: (SalesData sales, _) => sales.sales,
),

La valeur affiché est celle de votre axe des abscisses. Dans l’exemple que je montre ici, on parle donc des ventes.

Personnaliser vos axes

Les axes peuvent être ajustés pour améliorer la lisibilité :

  • primaryXAxis : Axe des X (ex. : NumericAxis, CategoryAxis).
  • primaryYAxis : Axe des Y.
  • Options : titre, intervalles, formatage.
SfCartesianChart(
  primaryXAxis: NumericAxis(
    title: AxisTitle(text: 'Années'), // Titre affiché sous l’axe X
    interval: 1, // Une marque tous les 1 an (2020, 2021, etc.)
  ),
  primaryYAxis: NumericAxis(
    title: AxisTitle(text: 'Ventes'), // Titre affiché à gauche de l’axe Y
    minimum: 20, // Valeur minimale des ventes
    maximum: 50, // Valeur maximale des ventes
    interval: 5, // Une marque tous les 5 unités (20, 25, 30, etc.)
  ),
  series: /* ... */,
),

Attention, les possibilités de personnalisation ne sont pas les mêmes selon le type d’axe. Voici les différentes variantes que vous pouvez utiliser :

TypeDonnées adaptéesExemple d’usage
NumericAxisNombres continusAnnées, quantités
CategoryAxisCatégories textuellesMois, noms de produits
DateTimeAxisDates/heures continuesVentes par jour
DateTimeCategoryAxisDates discrètesPremiers jours des mois
LogarithmicAxisDonnées exponentiellesCroissance logarithmique

Ajouter un un axe Y supplémentaire

Quand vos lignes représentent des données avec des unités ou des échelles différentes (ex. : ventes en k€ et taux de croissance en %), un seul axe Y peut rendre le graphique illisible. Avec la propriété axes de SfCartesianChart, vous pouvez ajouter un deuxième axe des ordonnées (ou plus), puis l’associer à une série via yAxisName.

Voici un exemple où une ligne montre les ventes (k€) et une autre le taux de croissance (%) :

SfCartesianChart(
  primaryXAxis: CategoryAxis(
    title: AxisTitle(text: 'Mois'),
  ),
  primaryYAxis: NumericAxis(
    title: AxisTitle(text: 'Ventes (k€)'),
    minimum: 20,
    maximum: 50,
  ),
  axes: <ChartAxis>[  // Ajoute les axes supplémentaires
    NumericAxis(
      name: 'secondYAxis',  // Nom unique pour cet axe
      title: AxisTitle(text: 'Taux de croissance (%)'),
      minimum: 0,
      maximum: 10,
      opposedPosition: true,  // Place l’axe à droite
    ),
  ],
  legend: Legend(isVisible: true),
  series: <LineSeries<SalesData, String>>[
    LineSeries<SalesData, String>(
      name: 'Ventes',
      dataSource: [
        SalesData('Jan', 35),
        SalesData('Fév', 28),
        SalesData('Mar', 34),
      ],
      xValueMapper: (SalesData sales, _) => sales.month,
      yValueMapper: (SalesData sales, _) => sales.sales,
      color: Colors.blue,
    ),
    LineSeries<SalesData, String>(
      name: 'Croissance',
      yAxisName: 'secondYAxis',  // Associe cette série au deuxième axe
      dataSource: [
        SalesData('Jan', 5.2),
        SalesData('Fév', 3.8),
        SalesData('Mar', 6.1),
      ],
      xValueMapper: (SalesData sales, _) => sales.month,
      yValueMapper: (SalesData sales, _) => sales.sales,
      color: Colors.red,
    ),
  ],
),

Ajouter un titre et une légende

Il est aussi possible d’ajouter un titre et une légende à votre graphique en ligne, pour améliorer sa compréhension.

  • title : Titre du graphique.
  • legend : Légende pour identifier les séries.
SfCartesianChart(
  title: ChartTitle(text: 'Évolution des ventes annuelles'),
  legend: Legend(isVisible: true),
  series: /* ... */,
),

Permettre les interactions avec le graphique

Ajoutez des fonctionnalités interactives :

  • tooltipBehavior : Affiche des info-bulles au survol.
  • trackballBehavior : Ligne verticale suivant le curseur.
class MyApp extends StatelessWidget {
  final TooltipBehavior _tooltip = TooltipBehavior(
    enable: true, // Active les tooltips
    color: Colors.red[800], // Couleur de fond pour mieux voir la bulle
    textStyle: TextStyle(color: Colors.white), // Texte lisible
  );
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SfCartesianChart(
          tooltipBehavior: _tooltip,
          trackballBehavior: TrackballBehavior(
            enable: true,
            lineType: TrackballLineType.vertical,
          ),
          series: /* ... */,
        ),
      ),
    );
  }
}

Modifier la durée de l’animation

Enfin, vous pouvez gérer la durée de l’animation d’entrée avec animationDuration (en millisecondes) :

LineSeries<SalesData, double>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.year,
  yValueMapper: (SalesData sales, _) => sales.sales,
  animationDuration: 5000, // 5 seconde
),

Avatar de Pierre Courtois