Hacer un gráfico de barras (Bar Chart) en Flutter


Avatar de Pedro Cortez

Ahora que hemos implementado syncfusion_flutter_charts, veamos cómo hacer un gráfico de barras, también llamado Bar Chart, en nuestra aplicación Flutter.


¿Para qué sirve un gráfico de barras?

Como los gráficos de columnas, los gráficos de barras son prácticos para comparar valores entre diferentes categorías o mostrar datos discretos, pero con una orientación horizontal. Cada barra representa un valor asociado a una categoría, con la longitud indicando la magnitud. Por lo tanto, son perfectos para:

  • Comparar rendimientos (por ejemplo: ventas por región).
  • Resaltar diferencias entre grupos (por ejemplo: gastos por departamento).
  • Presentar datos estáticos o puntuales (por ejemplo: puntuaciones de un equipo).

La orientación horizontal es particularmente útil cuando las etiquetas de las categorías son largas o numerosas, ofreciendo una mejor legibilidad que un gráfico de columnas verticales.

Crear un Bar Chart básico

Aquí tienes un ejemplo simple para mostrar datos de ventas anuales en varias regiones.

Asegúrate previamente de haber configurado syncfusion_flutter_charts añadiendo su dependencia en tu archivo 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('Bar Chart básico assim')),
        body: Center(
          child: SfCartesianChart(
            primaryXAxis: CategoryAxis(),
            series: <BarSeries<SalesData, String>>[
              BarSeries<SalesData, String>(
                dataSource: [
                  SalesData('Región A', 35),
                  SalesData('Región B', 28),
                  SalesData('Región C', 34),
                  SalesData('Región D', 32),
                  SalesData('Región E', 40),
                ],
                xValueMapper: (SalesData sales, _) => sales.region,
                yValueMapper: (SalesData sales, _) => sales.sales,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

Aquí están los elementos mínimos indispensables para hacer un gráfico de barras en Flutter:

  • SfCartesianChart: El contenedor principal para cualquier gráfico cartesiano (barras, columnas, líneas, etc.).
  • primaryXAxis: Define el eje horizontal. Sin esto, el gráfico no sabe cómo interpretar los datos X (aquí, CategoryAxis para regiones textuales).
  • series: La lista de series a mostrar. Sin series, no hay nada que dibujar.
  • BarSeries: Especifica que queremos un gráfico de barras horizontales (reemplaza a ColumnSeries).
  • dataSource: Los datos brutos en forma de lista de objetos, proporcionando los puntos a mostrar.
  • xValueMapper y yValueMapper: Conectan los datos a los ejes X (categorías) y Y (valores). Sin estos mappers, el gráfico no puede asociar los datos a los ejes.

Agregar varias barras a tu gráfico

Puedes mostrar aún más información en tu gráfico de barras al incluir varias series de datos para comparar categorías. Con syncfusion_flutter_charts, solo necesitas añadir varias BarSeries a la lista series de SfCartesianChart. Cada serie puede tener sus propios datos, colores y leyendas. Por defecto, las barras de diferentes series se colocan lado a lado gracias a la propiedad enableSideBySideSeriesPlacement.

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

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Bar Chart básico')),
        body: Center(
          child: SfCartesianChart(
            primaryXAxis: CategoryAxis(),
            series: <BarSeries<SalesData, String>>[
              BarSeries<SalesData, String>(
                dataSource: [
                  SalesData('Enero', 35, 'Región A'),
                  SalesData('Febrero', 28, 'Región A'),
                  SalesData('Marzo', 34, 'Región A'),
                  SalesData('Abril', 32, 'Región A'),
                  SalesData('Mayo', 40, 'Región A'),
                ],
                color: Colors.blue,
                xValueMapper: (SalesData sales, _) => sales.region,
                yValueMapper: (SalesData sales, _) => sales.sales,
              ),
              BarSeries<SalesData, String>(
                dataSource: [
                  SalesData('Enero', 30, 'Región B'),
                  SalesData('Febrero', 35, 'Región B'),
                  SalesData('Marzo', 20, 'Región B'),
                  SalesData('Abril', 26, 'Región B'),
                  SalesData('Mayo', 15, 'Región B'),
                ],
                color: Colors.red,
                xValueMapper: (SalesData sales, _) => sales.region,
                yValueMapper: (SalesData sales, _) => sales.sales,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

Si tus series tienen escalas muy diferentes (por ejemplo: una en miles, otra en unidades), puedes agregar un segundo eje Y adicional.

¿Cómo personalizar tu gráfico de barras?

syncfusion_flutter_charts ofrece numerosas opciones para personalizar un Bar Chart. Aquí tienes una lista detallada con ejemplos.

Cambiar la apariencia de las barras

Puedes modificar el color, la altura y el borde de las barras:

  • color: Color de relleno de las barras (Color como Colors.teal).
  • width: Altura relativa de las barras (entre 0 y 1, 1 = altura completa de la categoría).
  • borderWidth: Grosor del borde (en píxeles, por defecto 0).
  • borderColor: Color del borde (visible si borderWidth > 0).
BarSeries<SalesData, String>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.region,
  yValueMapper: (SalesData sales, _) => sales.sales,
  color: Colors.teal,
  width: 0.8, // 80% de la altura disponible
  borderWidth: 2,
  borderColor: Colors.black,
),

Agregar esquinas redondeadas

borderRadius permite redondear las extremidades de las barras (vía BorderRadius, por ejemplo: BorderRadius.circular(5)).

BarSeries<SalesData, String>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.region,
  yValueMapper: (SalesData sales, _) => sales.sales,
  borderRadius: BorderRadius.circular(5), // Esquinas redondeadas de 5 píxeles
),

Barras multicolores

pointColorMapper te permite asignar un color a cada barra mediante una función que devuelve un Color.

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

BarSeries<SalesData, String>(
  dataSource: [
    SalesData('Región A', 35, Colors.red),
    SalesData('Región B', 28, Colors.green),
    SalesData('Región C', 34, Colors.blue),
    SalesData('Región D', 32, Colors.yellow),
    SalesData('Región E', 40, Colors.purple),
  ],
  xValueMapper: (SalesData sales, _) => sales.region,
  yValueMapper: (SalesData sales, _) => sales.sales,
  pointColorMapper: (SalesData sales, _) => sales.color,
),

Agregar etiquetas de datos

dataLabelSettings te permite mostrar etiquetas de datos:

  • isVisible: true para mostrar las etiquetas.
  • labelAlignment: Posición (ChartDataLabelAlignment.middle, outer, etc.).
  • textStyle: Estilo del texto.
BarSeries<SalesData, String>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.region,
  yValueMapper: (SalesData sales, _) => sales.sales,
  dataLabelSettings: DataLabelSettings(
    isVisible: true,
    labelAlignment: ChartDataLabelAlignment.outer, // A la derecha de las barras
    textStyle: TextStyle(fontSize: 12, color: Colors.black),
  ),
),

Personalizar los ejes del gráfico

  • primaryXAxis: Define el tipo del eje horizontal. Por ejemplo, CategoryAxis (categorías textuales), NumericAxis (números), etc.
    • title: Añade un título mediante AxisTitle(text: ‘Mes’).
  • primaryYAxis: Eje vertical. Generalmente NumericAxis para las barras.
    • title: Título del eje Y.
    • minimum: Valor mínimo (por ejemplo: 0).
    • maximum: Valor máximo (por ejemplo: 50).
    • interval: Espaciado entre las marcas (por ejemplo: 10).
SfCartesianChart(
  primaryXAxis: CategoryAxis(
    title: AxisTitle(text: 'Regiones'),
  ),
  primaryYAxis: NumericAxis(
    title: AxisTitle(text: 'Ventas (k€)'),
    minimum: 0,
    maximum: 50,
    interval: 10,
  ),
  series: /* ... */,
),

Cuidado, las posibilidades de personalización no son las mismas según el tipo de eje. Aquí están las diferentes variantes que puedes usar:

TipoDatos adaptadosEjemplo de uso
NumericAxisNúmeros continuosAños, cantidades
CategoryAxisCategorías textualesMeses, nombres de productos
DateTimeAxisFechas/horas continuasVentas por día
DateTimeCategoryAxisFechas discretasPrimeros días de los meses
LogarithmicAxisDatos exponencialesCrecimiento logarítmico

Agregar un título y una leyenda

Es posible añadir un título y una leyenda a tu gráfico de barras, gracias a las siguientes propiedades:

  • title: ChartTitle(text: ‘Ventas por región’).
  • legend: Legend(isVisible: true).
SfCartesianChart(
  title: ChartTitle(text: 'Ventas por región 2025'),
  legend: Legend(isVisible: true),
  series: /* ... */,
),

Activar las interacciones

Puedes mostrar burbujas informativas en tus barras gracias a la propiedad tooltipBehavior. Para ello, deberás crear un widget de tipo TooltipBehavior, que contenga los siguientes elementos:

  • enable: true para activar.
  • color: Color de fondo (por ejemplo: Colors.grey).
  • textStyle: Estilo del texto en la burbuja.
class MyApp extends StatelessWidget {
  final TooltipBehavior _tooltip = TooltipBehavior(
    enable: true,
    color: Colors.grey[800],
    textStyle: TextStyle(color: Colors.white),
  );

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SfCartesianChart(
          tooltipBehavior: _tooltip,
          series: /* ... */,
        ),
      ),
    );
  }
}

Agregar un segundo eje Y con la propiedad axes

Cuando tus barras representan datos con unidades o escalas diferentes (por ejemplo: ventas en k€ y tasa de crecimiento en %), un solo eje Y puede hacer que el gráfico sea ilegible. Con la propiedad axes de SfCartesianChart, puedes añadir un segundo eje de ordenadas (o más), y luego asociarlo a una serie mediante yAxisName.

Aquí tienes un ejemplo donde una barra muestra las ventas (k€) y otra la tasa de crecimiento (%):

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Bar Chart básico')),
        body: Center(
          child: SfCartesianChart(
            primaryXAxis: CategoryAxis(
              title: AxisTitle(text: 'Regiones'),
            ),
            primaryYAxis: NumericAxis(
              title: AxisTitle(text: 'Ventas (k€)'),
              minimum: 20,
              maximum: 3000,
            ),
            axes: <ChartAxis>[
              NumericAxis(
                name: 'secondYAxis',
                title: AxisTitle(text: 'Crecimiento (%)'),
                minimum: 0,
                maximum: 12,
                opposedPosition: true,
              ),
            ],
            series: <BarSeries<SalesData, String>>[
              BarSeries<SalesData, String>(
                dataSource: [
                  SalesData('Enero', 1000),
                  SalesData('Febrero', 2000),
                  SalesData('Marzo', 1500),
                  SalesData('Abril', 2000),
                  SalesData('Mayo', 2500),
                ],
                color: Colors.blue,
                xValueMapper: (SalesData sales, _) => sales.month,
                yValueMapper: (SalesData sales, _) => sales.sales,
              ),
              BarSeries<SalesData, String>(
                yAxisName: 'secondYAxis',
                dataSource: [
                  SalesData('Enero', 5),
                  SalesData('Febrero', 2),
                  SalesData('Marzo', 10),
                  SalesData('Abril', 6),
                  SalesData('Mayo', 1),
                ],
                color: Colors.red,
                xValueMapper: (SalesData sales, _) => sales.month,
                yValueMapper: (SalesData sales, _) => sales.sales,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

Modificar la duración de la animación de aparición del gráfico

Por último, puedes alargar o acortar la duración de la animación de aparición del gráfico gracias a la propiedad animationDuration:

BarSeries<SalesData, String>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.region,
  yValueMapper: (SalesData sales, _) => sales.sales,
  animationDuration: 5000, // En milisegundos
),
Avatar de Pedro Cortez