Crear un gráfico de columnas (Column 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 columnas?

Los gráficos de columnas son ideales para comparar valores entre diferentes categorías o mostrar datos discretos. Cada columna representa un valor asociado a una categoría, con la altura indicando la magnitud. Son úteles para:

  • Comparar desempeños (ej.: ventas por mes).
  • Destacar diferencias entre grupos (ej.: ingresos por región).
  • Presentar datos estáticos o puntuales (ej.: puntajes de un equipo).

Crear un column chart básico

Aquí hay un ejemplo simple para mostrar datos de ventas anuales.

Asegúrese de haber configurado correctamente syncfusion_flutter_charts agregando su dependencia en el 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('Column Chart básico')),
        body: Center(
          child: SfCartesianChart(
            primaryXAxis: CategoryAxis(),
            series: <ColumnSeries<SalesData, String>>[
              ColumnSeries<SalesData, String>(
                dataSource: [
                  SalesData('Ene', 35),
                  SalesData('Feb', 28),
                  SalesData('Mar', 34),
                  SalesData('Abr', 32),
                  SalesData('May', 40),
                ],
                xValueMapper: (SalesData sales, _) => sales.month,
                yValueMapper: (SalesData sales, _) => sales.sales,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

Elementos clave para un gráfico de columnas en Flutter:

  • SfCartesianChart: Contenedor principal para todos los gráficos cartesianos (columnas, líneas, etc.).
  • primaryXAxis: Define el eje horizontal. Sin esto, el gráfico no puede interpretar los datos X (aqui, CategoryAxis para meses en texto).
  • series: Lista de series a mostrar.
  • ColumnSeries: Especifica que el gráfico es de tipo columna.
  • dataSource: Datos en forma de lista de objetos, que proporcionan los puntos a mostrar.
  • xValueMapper y yValueMapper: Conectan los datos con los ejes X (categorías) y Y (valores). Sin estos mapeos, el gráfico no puede asociar los datos con los ejes.

Agregar varias columnas al gráfico

Se puede hacer el gráfico más potente agregando varias series de datos para comparar categorías. Con syncfusion_flutter_charts, simplemente agregue múltiples ColumnSeries a la lista series de SfCartesianChart. Cada serie puede tener sus propios datos, colores y leyendas. Por defecto, las columnas de diferentes series se colocan una al lado de la otra gracias a la propiedad enableSideBySideSeriesPlacement.

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('Column Chart con varias columnas')),
        body: SfCartesianChart(
          title: ChartTitle(text: 'Ventas por región (2025)'),
          legend: Legend(isVisible: true),
          tooltipBehavior: _tooltip,
          primaryXAxis: CategoryAxis(
            title: AxisTitle(text: 'Mes'),
          ),
          primaryYAxis: NumericAxis(
            title: AxisTitle(text: 'Ventas (k€)')
          ),
          series: <ColumnSeries<SalesData, String>>[
            ColumnSeries<SalesData, String>(
              name: 'Región A',
              dataSource: [
                SalesData('Ene', 35),
                SalesData('Feb', 28),
                SalesData('Mar', 34),
                SalesData('Abr', 32),
                SalesData('May', 40),
              ],
              xValueMapper: (SalesData sales, _) => sales.month,
              yValueMapper: (SalesData sales, _) => sales.sales,
              color: Colors.blue,
            ),
            ColumnSeries<SalesData, String>(
              name: 'Región B',
              dataSource: [
                SalesData('Ene', 25),
                SalesData('Feb', 30),
                SalesData('Mar', 27),
                SalesData('Abr', 35),
                SalesData('May', 38),
              ],
              xValueMapper: (SalesData sales, _) => sales.month,
              yValueMapper: (SalesData sales, _) => sales.sales,
              color: Colors.red,
            ),
          ],
        ),
      ),
    );
  }
}

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

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

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

Cambiar la apariencia de las columnas

Puedes modificar el color, el ancho y el borde de las columnas:

  • color: Define el color de relleno de las columnas. Acepta un Color (por ejemplo: Colors.teal, Color.fromRGBO(255, 0, 0, 1)).
  • width: Controla el ancho relativo de las columnas en el espacio asignado a cada categoría. Valor entre 0 y 1 (1 = ancho completo, 0.5 = mitad del espacio).
  • borderWidth: Grosor del borde alrededor de las columnas, en píxeles (por ejemplo: 2.0). Por defecto, 0 (sin borde).
  • borderColor: Color del borde. Requiere borderWidth > 0 para ser visible.
ColumnSeries<SalesData, String>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.month,
  yValueMapper: (SalesData sales, _) => sales.sales,
  color: Colors.teal,
  width: 0.8, // 80% del espacio disponible por columna
  borderWidth: 2,
  borderColor: Colors.black,
),

Agregar esquinas redondeadas

borderRadius redondea las esquinas superiores de las columnas gracias al widget BorderRadius.

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

Columnas multicolores

Utiliza pointColorMapper para asignar un color diferente a cada columna:

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

ColumnSeries<SalesData, String>(
  dataSource: [
    SalesData('Ene', 35, Colors.red),
    SalesData('Feb', 28, Colors.green),
    SalesData('Mar', 34, Colors.blue),
    SalesData('Abr', 32, Colors.yellow),
    SalesData('May', 40, Colors.purple),
  ],
  xValueMapper: (SalesData sales, _) => sales.month,
  yValueMapper: (SalesData sales, _) => sales.sales,
  pointColorMapper: (SalesData sales, _) => sales.color,
),

Piensa en añadir una propiedad Color a la clase que te permitirá generar tus columnas.

Agregar varias columnas al gráfico

El widget SfCartesianChart te permite mostrar varias series de datos para comparar categorías, cada una con sus colores y leyendas.

Para ello, utiliza la propiedad enableSideBySideSeriesPlacement que permite colocar las columnas lado a lado cuando tiene un valor de true, y se superponen cuando tiene un valor de false.

SfCartesianChart(
  title: ChartTitle(text: 'Ventas por región (2025)'),
  legend: Legend(isVisible: true),
  primaryXAxis: CategoryAxis(title: AxisTitle(text: 'Mes')),
  primaryYAxis: NumericAxis(title: AxisTitle(text: 'Ventas (k€)')),
  series: <ColumnSeries<SalesData, String>>[
    ColumnSeries<SalesData, String>(
      name: 'Región A', // Nombre en la leyenda
      dataSource: [
        SalesData('Ene', 35),
        SalesData('Feb', 28),
        SalesData('Mar', 34),
      ],
      xValueMapper: (SalesData sales, _) => sales.month,
      yValueMapper: (SalesData sales, _) => sales.sales,
      color: Colors.blue,
    ),
    ColumnSeries<SalesData, String>(
      name: 'Región B',
      dataSource: [
        SalesData('Ene', 25),
        SalesData('Feb', 30),
        SalesData('Mar', 27),
      ],
      xValueMapper: (SalesData sales, _) => sales.month,
      yValueMapper: (SalesData sales, _) => sales.sales,
      color: Colors.red,
    ),
  ],
),

Agregar etiquetas de datos

Con dataLabelSettings, muestra los valores de tus columnas directamente encima:

  • isVisible: true para mostrar las etiquetas, false para ocultarlas.
  • labelAlignment: Posición de la etiqueta (ChartDataLabelAlignment.top, middle, bottom, etc.).
  • textStyle: Estilo del texto (por ejemplo: TextStyle(fontSize: 12, color: Colors.black)).
ColumnSeries<SalesData, String>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.month,
  yValueMapper: (SalesData sales, _) => sales.sales,
  dataLabelSettings: DataLabelSettings(
    isVisible: true,
    labelAlignment: ChartDataLabelAlignment.top,
    textStyle: TextStyle(fontSize: 12, color: Colors.black),
  ),
),

Personalizar los ejes

Puedes personalizar los ejes de tu grafico, con las propriedades siguentes :

  • 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 columnas.
    • 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: 'Mes'), // Título del eje X
  ),
  primaryYAxis: NumericAxis(
    title: AxisTitle(text: 'Ventas (k€)'), // Título del eje Y
    minimum: 0, // Comienza en 0
    maximum: 50, // Termina en 50
    interval: 10, // Marcas cada 10 k€
  ),
  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

También puedes añadir un título y una leyenda a tu gráfico, gracias a las siguientes propiedades:

  • title: Título global del gráfico mediante ChartTitle.
  • legend: Muestra una leyenda para identificar las series.
SfCartesianChart(
  title: ChartTitle(text: 'Ventas mensuales 2025'), // Título del gráfico
  legend: Legend(isVisible: true), // Leyenda visible
  series: /* ... */,
),

Activar las interacciones

Puedes mostrar burbujas informativas en tus columnas 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, // Activa los tooltips
    color: Colors.grey[800], // Fondo gris oscuro
    textStyle: TextStyle(color: Colors.white), // Texto blanco
  );

  @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 líneas 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 columna muestra las ventas (k€) y otra la tasa de crecimiento (%):

SfCartesianChart(
  title: ChartTitle(text: 'Ventas por región (2025)'),
  legend: Legend(
    isVisible: true), // Activa la leyenda para identificar las columnas
  tooltipBehavior: _tooltip,
  primaryXAxis: CategoryAxis(
    title: AxisTitle(text: 'Mes'),
  ),
  primaryYAxis: NumericAxis(
    title: AxisTitle(text: 'Ventas (k€)'),
    minimum: 20,
    maximum: 50,
  ),
  axes: <ChartAxis>[
    // Agrega los ejes adicionales
    NumericAxis(
      name: 'secondYAxis', // Nombre único para este eje
      title: AxisTitle(text: 'Tasa de crecimiento (%)'),
      minimum: 0,
      maximum: 10,
      opposedPosition: true, // Coloca el eje a la derecha
    ),
  ],
  series: <ColumnSeries<SalesData, String>>[
    // Primera serie: Región A
    ColumnSeries<SalesData, String>(
      dataSource: [
        SalesData('Ene', 35),
        SalesData('Feb', 28),
        SalesData('Mar', 34),
        SalesData('Abr', 32),
        SalesData('May', 40),
      ],
      dataLabelSettings: DataLabelSettings(
        isVisible: true,
        labelAlignment: ChartDataLabelAlignment.top,
        textStyle: TextStyle(fontSize: 12, color: Colors.black),
      ),
      xValueMapper: (SalesData sales, _) => sales.month,
      yValueMapper: (SalesData sales, _) => sales.sales,
      color: Colors.blue, // Color de las columnas
      width: 0.8,
    ),
    ColumnSeries<SalesData, String>(
      yAxisName: 'secondYAxis',
      dataSource: [
        SalesData('Ene', 0.5),
        SalesData('Feb', 1),
        SalesData('Mar', 3),
        SalesData('Abr', 1.5),
        SalesData('May', 4),
      ],
      dataLabelSettings: DataLabelSettings(
        isVisible: true,
        labelAlignment: ChartDataLabelAlignment.top,
        textStyle: TextStyle(fontSize: 12, color: Colors.black),
      ),
      xValueMapper: (SalesData sales, _) => sales.month,
      yValueMapper: (SalesData sales, _) => sales.sales,
      color: Colors.red, // Color de las columnas
      width: 0.8,
    ),
  ],
),

Modificar la duración de la animación

Por último, puedes gestionar la duración de la animación de entrada de tu gráfico de columnas con animationDuration (en milisegundos):

LineSeries<SalesData, double>(
  dataSource: /* ... */,
  xValueMapper: (SalesData sales, _) => sales.year,
  yValueMapper: (SalesData sales, _) => sales.sales,
  animationDuration: 5000, // 5 segundos
),
Avatar de Pedro Cortez