# Create an Interactive Heat Map Using Flutter Charts

**TL;DR:** Learn to create an interactive heat map using the Flutter Charts. You’ll learn to add dependencies, populate a custom data source, set up a StackedBar100Series for data visualization, and customize the heat map renderer, labels, axes, and colors for a more tailored, interactive experience.

Welcome to our **Chart of the Week** blog series!

In this blog, we’ll explain how to create a Heat Map Chart using the Syncfusion [Flutter Charts](https://www.syncfusion.com/flutter-widgets/flutter-charts), a handy tool for developers. With just a few simple steps, you can turn large amounts of data into a clear, colorful chart, making it easier to spot patterns, trends, and outliers.

The [onCreateRenderer](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianSeries/onCreateRenderer.html) callback allows you to customize the appearance of the heat map chart by creating a custom series renderer. You can use a custom renderer like \_**HeatmapSeriesRenderer** to control how the data is displayed. The [populateDataSource](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianSeriesRenderer/populateDataSource.html) method organizes raw data into a structured format, making the chart more interactive and dynamic. The custom series enables you to modify the default chart behavior, allowing for unique visual effects.

## What is a Heat Map?

A [heat map](https://en.wikipedia.org/wiki/Heat_map) is a data visualization technique used to represent data in a two-dimensional format, where colors indicate different values. It helps make complex data easier to understand by showing patterns, trends, and differences through various shades of color.

In a heat map, data is arranged in a grid or table, with each cell representing a value. The color of each cell changes based on the data, with darker or lighter colors usually indicating higher or lower values. This makes it easy to compare information quickly.

**Use cases of heat maps:**

* **Website and user behavior analysis:** Helps to track where users click, scroll, and spend time improving website design.
    
* **Business and market analysis:** Identifies sales trends, customer behavior, and market performance to aid decision-making.
    
* **Geographic and weather mapping:** Displays temperature variations, rainfall distributions, and population densities across regions.
    
* **Healthcare and medical research:** Monitors disease outbreaks, patient health records, and the utilization of hospital resources.
    
* **Sports and performance analytics:** Analyzes player movements, ball possession, and team strategies to enhance performance.
    

## Creating a heat map using Flutter Charts

To create a heat map chart in Flutter, we’ll use the Syncfusion Flutter Charts package. This guide will walk you through each step required to implement a heat map chart using the [StackedBar100Series](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/StackedBar100Series-class.html) in the [SfCartesianChart](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCartesianChart-class.html).

### Step 1: Add dependencies

To get started, add the [Syncfusion Flutter Charts](https://pub.dev/packages/syncfusion_flutter_charts/versions) package to your **pubspec.yaml** file.

```javascript
dependencies:
  flutter:
    sdk: flutter
  syncfusion_flutter_charts: ^xx.x.x  # Replace with the latest version
```

### Step 2: Populate the data source

Then, we need to define the dataset for our heat map. The **\_HeatMapData** class represents data points with multiple numerical values.

```javascript
class _HeatMapData {
  final String percentage;
  final double nancy;
  final double andrew;
  final double janet;
  final double margaret;
  final double steven;
  final double michael;
  final double robert;
  final double laura;
  final double anne;
  final double paul;
  final double mario;

  _HeatMapData(
    this.percentage,
    this.nancy,
    this.andrew,
    this.janet,
    this.margaret,
    this.steven,
    this.michael,
    this.robert,
    this.laura,
    this.anne,
    this.paul,
    this.mario,
  );
}
```

Now, we can populate the dataset using the **initState** method.

```javascript
@override
void initState() {
    _heatMapData = <_HeatMapData>[
      _HeatMapData('Mon', 0.694, 27, 0.285, 0.76, 0.375, 10, 3, 4, 2, 5, 30),
      _HeatMapData('Tue', 15, 1.68, 50, 1.61, 1.75, 1.61, 60, 40, 150, 40, 0.1),
      _HeatMapData('Wed', 0.5, 0.15, 90, 0.6, 0.25, 7, 2, 3, 1, 4, 20),
      _HeatMapData('Thu', 0.3, 80, 0.1, 0.4, 112, 4, 1, 50, 0, 2, 40),
      _HeatMapData('Fri', 0.5, 0.15, 90, 0.6, 0.25, 7, 2, 3, 1, 4, 20),
      _HeatMapData('Sat', 6.9, 43.2, 40.8, 69.5, 49.5, 5.7, 80, 20, 12, 40, 9),
    ];
    super.initState();
}
```

### Step 3: Set up a StackedBar100Series

Here, we’ll create the heat map using the [StackedBar100Series](https://help.syncfusion.com/flutter/cartesian-charts/chart-types/stacked-bar-100-chart) from [SfCartesianChart](https://help.syncfusion.com/flutter/cartesian-charts/overview). The \_**buildHeatmapSeries** method is used to generate 11 stacked bar series, each showing a different part of the data.

The [xValueMapper](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartSeries/xValueMapper.html) sets the percentage value from ***HeatMapData*** *on the x-axis, while the* ***yValueMapper*** *uses* **findValueByIndex** to get the correct y-axis value for each segment.

The [pointColorMapper](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartSeries/pointColorMapper.html) decides the color based on the data value using \_**buildColor**, making it easier to see differences. The [dataLabelSettings](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartSeries/dataLabelSettings.html) feature is enabled by setting the [isVisible](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/isVisible.html) property to **true** to show labels inside each segment. This setup keeps the heat map clear, colorful, and easy to understand.

```javascript
SfCartesianChart(
  series: _buildHeatmapSeries(),
);

List<CartesianSeries<_HeatMapData, String>> _buildHeatmapSeries() {
  return List.generate(11, (index) {
    return StackedBar100Series<_HeatMapData, String>(
      dataSource: _heatMapData,
      xValueMapper: (_HeatMapData data, int _) => data.percentage,
      yValueMapper: (_HeatMapData data, int _) => _findValueByIndex(data, index),
      pointColorMapper: (_HeatMapData data, int _) =>
          _buildColor(_findValueByIndex(data, index)),
      ....
      dataLabelSettings: DataLabelSettings(
        isVisible: true,
      ),
      ....
    );
  });
}
```

### Step 4: Create and configure a custom heat map series renderer

In this step, we’ll create a custom renderer for the heat map series by extending the [StackedBar100SeriesRenderer](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/StackedBar100SeriesRenderer-class.html) class. This will allow us to customize how the heat map data is processed and displayed in Syncfusion Flutter Charts. This customization is done using the [onCreateRenderer](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianSeries/onCreateRenderer.html) property of the [StackedBar100Series](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/StackedBar100Series-class.html).

#### Calculate the default range

The heat map visualization needs to maintain a consistent value range to ensure proper color representation.

* We override the [populateDataSource](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CartesianSeriesRenderer/populateDataSource.html) method to set a fixed range for the y-axis values.
    
* The **yMin** is set to **0**, and the **yMax** is set to **101**, meaning the heat map will always represent values within this range, even if negative values are present in the dataset. This step helps keep the chart balanced, making it easier to compare different data points.
    

```javascript
class _HeatmapSeriesRenderer extends StackedBar100SeriesRenderer<_HeatMapData, String> {
  _HeatmapSeriesRenderer();

  @override
  void populateDataSource(
    [
      List<ChartValueMapper<_HeatMapData, num>>? yPaths,
      List<List>? chaoticYLists,
      List<List>? yLists,
      List<ChartValueMapper<_HeatMapData, Object>>? fPaths,
      List<List<Object?>>? chaoticFLists,
      List<List<Object?>>? fLists
    ]
  ) {
    super.populateDataSource(
      yPaths, chaoticYLists, yLists, fPaths, chaoticFLists, fLists
    );

    // Always keep positive 0 to 101 range even set negative value.
    yMin = 0;
    yMax = 101;

    // Calculate heatmap segment top and bottom values.
    _computeHeatMapValues();
  }
  ....
}
```

#### Calculate the heat map values

We calculate the top and bottom values for each segment using the **\_computeHeatMapValues()** method, ensuring they are evenly distributed, which makes the chart visually balanced.

The height of each segment is determined using the formula **yValue** = 100 / **seriesLength**, where **seriesLength** is the number of series dependent on the y-axis. For each series, we skip those that are not visible or have no data, then assign the bottom value based on its position and set the top value as **stackValue** + **yValue**.

Finally, we loop through the data points and apply these values, ensuring all segments maintain a consistent height across the heatmap.

```javascript
class _HeatmapSeriesRenderer extends StackedBar100SeriesRenderer<_HeatMapData, String> {
  _HeatmapSeriesRenderer();
  ....  
  _computeHeatMapValues();
}

void _computeHeatMapValues() {
  if (xAxis == null || yAxis == null) {
    return;
  }

  if (yAxis!.dependents.isEmpty) {
    return;
  }

  // Get the number of series dependent on the yAxis.
  final int seriesLength = yAxis!.dependents.length;
  // Calculate the proportional height for each series (as a percentage of the total height).
  final num yValue = 100 / seriesLength;
  // Loop through each dependent series to calculate top and bottom values for the heatmap.
  for (int i = 0; i < seriesLength; i++) {
    // Check if the current series is a '_HeatmapSeriesRenderer'.
    if (yAxis!.dependents[i] is _HeatmapSeriesRenderer) {
      final _HeatmapSeriesRenderer current =
          yAxis!.dependents[i] as _HeatmapSeriesRenderer;

      // Skip processing if the series is not visible or has no data.
      if (!current.controller.isVisible || current.dataCount == 0) {
        continue;
      }

      // Calculate the bottom (stack) value for the current series.
      num stackValue = 0;
      stackValue = yValue * i;

      current.topValues.clear();
      current.bottomValues.clear();

      // Loop through the data points in the current series.
      final int length = current.dataCount;
      for (int j = 0; j < length; j++) {
        // Add the bottom value (stackValue) for the current data point.
        current.bottomValues.add(stackValue.toDouble());
        // Add the top value (stackValue + yValue) for the current data point.
        current.topValues.add((stackValue + yValue).toDouble());
      }
    }
  }
}
```

#### Configure axes and disable gridline appearance

In the \_**buildHeatmapChart()** method, the [primaryXAxis](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCartesianChart/primaryXAxis.html) is set to a [CategoryAxis](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/CategoryAxis-class.html). The [axisLine](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/axisLine.html), [majorGridLines](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/majorGridLines.html), and [majorTickLines](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/majorTickLines.html) are all disabled by setting their widths to 0. This removes unnecessary visual elements, making the heat map more straightforward. The label text is also formatted in bold with a font size of 14.

For the [primaryYAxis](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCartesianChart/primaryYAxis.html), a [NumericAxis](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/NumericAxis-class.html) is used, positioned on the opposite side by setting the [opposedPosition](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/opposedPosition.html) property to **true.** Like the X-axis, the [opposedPosition](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/opposedPosition.html), [majorGridLines](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/majorGridLines.html), and [majorTickLines](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartAxis/majorTickLines.html) of the Y-axis are also hidden to keep the chart simple.

Additionally, the y-axis also includes [multiLevelLabels](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/NumericAxis/multiLevelLabels.html), created using ***buildNumericLabels(),*** *with a transparent border to ensure a seamless look. The* [*multiLevelLabels*](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/NumericAxis/multiLevelLabels.html) *property in the* [*NumericAxis*](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/NumericAxis-class.html) *applies the* **buildNumericLabels()** method to ensure custom numeric labels, and these labels are further formatted using the \_**formatLabel()** method for bold styling. By setting the [labelStyle](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/AxisLabel/labelStyle.html) to have a **font size** of 0, the axis labels are effectively hidden.

By removing gridlines and customizing axis labels, this setup makes the heat map clearer and easier to read without extra distractions.

```javascript
List<NumericMultiLevelLabel> _buildNumericLabels() {
  return [
    NumericMultiLevelLabel(start: 0, end: 8, text: 'Nancy'),
    NumericMultiLevelLabel(start: 8, end: 19, text: 'Andrew'),
    NumericMultiLevelLabel(start: 19, end: 26, text: 'Janet'),
    NumericMultiLevelLabel(start: 26, end: 38, text: 'Margaret'),
    NumericMultiLevelLabel(start: 38, end: 43, text: 'Steven'),
    NumericMultiLevelLabel(start: 43, end: 56, text: 'Michael'),
    NumericMultiLevelLabel(start: 56, end: 62, text: 'Robert'),
    NumericMultiLevelLabel(start: 62, end: 75, text: 'Laura'),
    NumericMultiLevelLabel(start: 75, end: 80, text: 'Anne'),
    NumericMultiLevelLabel(start: 80, end: 92, text: 'Paul'),
    NumericMultiLevelLabel(start: 92, end: 98, text: 'Mario'),
  ];
}

ChartAxisLabel _formatLabel(MultiLevelLabelRenderDetails details) {
  return ChartAxisLabel(
    details.text,
    const TextStyle(fontWeight: FontWeight.bold, fontSize: 14.0)
  );
}

SfCartesianChart(
  ....
  primaryXAxis: CategoryAxis(
    axisLine: const AxisLine(width: 0),
    majorGridLines: const MajorGridLines(width: 0),
    majorTickLines: const MajorTickLines(width: 0),
    labelStyle: const TextStyle(
      fontWeight: FontWeight.bold,
      fontSize: 14.0
    ),
  ),
  primaryYAxis: NumericAxis(
    opposedPosition: true,
    axisLine: const AxisLine(width: 0),
    majorGridLines: const MajorGridLines(width: 0),
    majorTickLines: const MajorTickLines(width: 0),
    labelStyle: const TextStyle(fontSize: 0),
    multiLevelLabelStyle: MultiLevelLabelStyle(borderColor: Colors.transparent),
    multiLevelLabels: _buildNumericLabels(),
    multiLevelLabelFormatter: _formatLabel
  ),
  ....
);
```

Refer to the following image.

![Configuring axes and disabling gridline appearance in Flutter Heat map](https://www.syncfusion.com/blogs/wp-content/uploads/2025/02/image001-4.png align="left")

Configuring axes and disabling gridline appearance in Flutter Heat map

#### Customizing heat map appearance

The heat map is designed to be clear and easy to understand by adjusting colors, borders, and labels. The [pointColorMapper](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartSeries/pointColorMapper.html) property in the [StackedBar100Series](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/StackedBar100Series-class.html) automatically assigns colors to each segment based on its data value. This helps display different intensity levels in the chart.

The [width](https://help.syncfusion.com/flutter/cartesian-charts/chart-types/stacked-bar-100-chart?_gl=1*1wibffq*_ga*NDkxMjAyNzUxLjE3MzA2NDIyNTk.*_ga_41J4HFMX1J*MTczOTQ1OTQxMC40OC4xLjE3Mzk0NjA4NjAuMC4wLjA.#bar-width-and-spacing) property controls the size of each segment, keeping the layout organized. The [borderColor](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/StackedBar100Series/borderColor.html) makes the segment edges clear.

The ***findValueByIndex*** *function retrieves the correct data value for each segment, while* **buildColor** assigns a color based on that value, creating a smooth color gradient for better visualization. The **animationDuration** is set to 0 to ensure the heat map appears instantly without any delay.

```javascript
Color _buildColor(num value) {
  if (value >= 100.0) return Colors.lightBlue.shade800;
  if (value >= 80.0) return Colors.lightBlue.shade700;
  if (value >= 50.0) return Colors.lightBlue.shade600;
  if (value >= 40.0) return Colors.lightBlue.shade500;
  if (value >= 20.0) return Colors.lightBlue.shade400;
  if (value >= 0.0) return Colors.lightBlue.shade300;
  return Colors.redAccent.shade100;
}

double _findValueByIndex(_HeatMapData data, int index) {
  switch (index) {
    case 0:
      return data.nancy;
    case 1:
      return data.andrew;
    case 2:
      return data.janet;
    case 3:
      return data.margaret;
    case 4:
      return data.steven;
    case 5:
      return data.michael;
    case 6:
      return data.robert;
    case 7:
      return data.laura;
    case 8:
      return data.anne;
    case 9:
      return data.paul;
    case 10:
      return data.mario;
    default:
      return 0;
  }
}

StackedBar100Series<_HeatMapData, String>(
  ....
  pointColorMapper: (_HeatMapData data, int _) => _buildColor(_findValueByIndex(data, index)),
  ....
  animationDuration: 0,
  width: 1,
  borderWidth: 1,
  borderColor: Colors.lightBlue.shade600,
),
....
);
```

Refer to the following image.

![Customizing appearance in Heat map](https://www.syncfusion.com/blogs/wp-content/uploads/2025/02/image003-4.png align="left")

Customizing appearance in Heat map

### Step 5: Adding data labels

The [dataLabelSettings](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartSeries/dataLabelSettings.html) property in the [StackedBar100Series](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/StackedBar100Series-class.html) is used to display labels on each heat map segment, making it easier to interpret the data. The [isVisible](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/isVisible.html) property is set to **true,** ensuring that the labels appear on the chart. The [labelAlignment](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/DataLabelSettings/labelAlignment.html) is set to [ChartDataLabelAlignment](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartDataLabelAlignment.html) with the value as middle, which places the labels at the center of each segment for better readability.

These settings help users quickly understand the data by displaying values directly on the heat map segments.

```javascript
StackedBar100Series<_HeatMapData, String>(
  ....
  dataLabelSettings: DataLabelSettings(
    isVisible: true,
    labelAlignment: ChartDataLabelAlignment.middle,
    textStyle: const TextStyle(
      fontSize: 15,
      color: Colors.black,
      fontWeight: FontWeight.bold,
    ),
  ),
  ....
);
```

Refer to the following image.

![Adding data labels in the Flutter heat map](https://www.syncfusion.com/blogs/wp-content/uploads/2025/02/image005-2.png align="left")

Adding data labels in the Flutter heat map

### Step 6: Adding legend

The [legend](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCircularChart/legend.html) helps users understand the color variations in the heat map. In the [SfCartesianChart](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCartesianChart-class.html), the **Legend** property is enabled by setting the [isVisible](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/isVisible.html) property to true, and the [legend](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCircularChart/legend.html) is placed at the top by setting the [LegendPosition](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/LegendPosition.html) property. The [legendItemBuilder](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/Legend/legendItemBuilder.html) is used to create a custom [legend](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCircularChart/legend.html), displaying a gradient color bar from red to light blue, representing the data range from Zero to 150.

The [isVisibleInLegend](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/ChartSeries/isVisibleInLegend.html) property in the [StackedBar100Series](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/StackedBar100Series-class.html) ensures that only the first series’ [legend](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCircularChart/legend.html) is shown. This makes the chart easier to understand by showing how colors match data values.

```javascript
SfCartesianChart(
  ....
  legend: Legend(
    isVisible: true,
    position: LegendPosition.top,
    toggleSeriesVisibility: false,
    legendItemBuilder: (legendText, series, point, seriesIndex) {
      return Row(
        children: [
          const Text('Zero '),
          const SizedBox(width: 5),
          SizedBox(
            width: 400,
            height: 20,
            child: DecoratedBox(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [
                    Colors.lightBlue.withValues(alpha: 0.1),
                    Colors.lightBlue.withValues(alpha: 0.4),
                    Colors.lightBlue.withValues(alpha: 0.9),
                  ],
                  begin: Alignment.centerLeft,
                  end: Alignment.centerRight,
                ),
              ),
            ),
          ),
          const SizedBox(width: 5),
          const Text('150'),
        ],
      );
    },
  ),
  ....       
  series: _buildHeatmapSeries(),
);

List<CartesianSeries<_HeatMapData, String>> _buildHeatmapSeries() {
  return List.generate(11, (index) {
    return StackedBar100Series<_HeatMapData, String>(
      ....    
      isVisibleInLegend: index == 0,
      ....   
    );
  });
}
```

Refer to the following image.

![Adding legend in Flutter heat map](https://www.syncfusion.com/blogs/wp-content/uploads/2025/02/image007.png align="left")

Adding legend in Flutter heat map

### Step 7: Adding tooltip

The tooltip feature is enabled using the [TooltipBehavior](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/SfCartesianChart/tooltipBehavior.html) to make the chart more interactive and user-friendly. This allows users to see detailed information when they hover over a data point.

* The [tooltipPosition](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipPosition.html) is set to **TooltipPosition.pointer**, so the tooltip moves with the cursor or touch point for easier tracking.
    
* The [format](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/format.html) property is used to display both X and Y values **(point.x : point.y).**
    
* The [header](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/header.html) is set to **Person,** providing a clear label for the tooltip.
    
* The [animationDuration](https://pub.dev/documentation/syncfusion_flutter_charts/latest/charts/TooltipBehavior/animationDuration.html) is set to 0 to ensure the tooltip appears instantly without delay.
    

This setup improves readability and provides instant insights when interacting with the heat map.

```javascript
class HeatMapState extends State<HeatMap> {
  ....
  TooltipBehavior? _tooltipBehavior;

  @override
  void initState() {
    ....
    _tooltipBehavior = TooltipBehavior(
      enable: true,
      header: 'Person', 
      animationDuration: 0,
      tooltipPosition: TooltipPosition.pointer,
      format: 'point.x : point.y',
    );
    super.initState();
  }

  SfCartesianChart(  
    ....  
    tooltipBehavior: _tooltipBehavior,
  );
}
```

Refer to the following image.

![Adding tooltip to Flutter heat map](https://www.syncfusion.com/blogs/wp-content/uploads/2025/02/image009-1.png align="left")

Adding tooltips to Flutter heat map

## GitHub reference

For more details, refer to the [creating a heat map using the Flutter Charts demo on GitHub](https://github.com/SyncfusionExamples/flutter_chart_heatmap).

## Conclusion

Thanks for reading! This blog explains creating a heat map using the Syncfusion [Flutter Charts](https://www.syncfusion.com/flutter-widgets/flutter-charts). We hope these steps help you easily create a similar heat map and enhance your data visualization.

The existing customers can download the new version of Essential Studio on the [License and Downloads](https://www.syncfusion.com/account) page. If you are not a Syncfusion customer, try our 30-day [free trial](https://www.syncfusion.com/downloads) to check out our incredible features.

You can also contact us through our [support forums](https://www.syncfusion.com/forums), [support portal](https://support.syncfusion.com/), or [feedback portal](https://www.syncfusion.com/feedback/flutter). We are always happy to assist you!

## Related Blogs

[**Customize Flutter DataGrid for Enhanced Data Visualization**](https://www.syncfusion.com/blogs/post/customize-flutter-data-grid-widget)7 min read

[**Flutter DataGrid: How to Group Data Easily**](https://www.syncfusion.com/blogs/post/grouping-data-in-flutter-datagrid)7 min read

[**AI-Powered Smart Flutter Spline Chart for Web Traffic Analytics**](https://www.syncfusion.com/blogs/post/web-traffic-data-flutter-spline-chart)12 min read

[**Unlock Insight in**](https://www.syncfusion.com/blogs/post/flutter-range-column-chart-g7-debt)**harts**[**to G7 Countries’ Debt with the Flutter Range Column Chart**](https://www.syncfusion.com/blogs/post/flutter-range-column-chart-g7-debt)13 min read
