> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cristalyse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Heat Map Charts

> Visualize 2D data patterns with color-coded intensity heat maps

<Card title="View Live Example" icon="play" href="https://example.cristalyse.com/#/heatmap" target="_blank">
  See heat map charts in action with interactive examples
</Card>

## Overview

Heat maps are perfect for visualizing 2D data patterns where color intensity represents value magnitude. Cristalyse heat maps support customizable color schemes (via `colorGradient`), interactive tooltips, and responsive layouts for effective data exploration.

<Note>
  **API Note**: Heat maps use `.mappingHeatMap()` instead of `.mapping()`, and color gradients are specified via the `colorGradient` parameter in `.geomHeatMap()`. If no `colorGradient` is specified, the default `GradientColorScale.heatMap()` gradient (dark blue → cyan → lime green → bright red) is automatically applied.
</Note>

<div align="center">
  <em>Heat maps with customizable color gradients and interactive cell highlighting</em>
</div>

## Basic Heat Map

Create a simple heat map to show data density:

```dart theme={null}
final performanceData = [
  {'region': 'North', 'month': 'Jan', 'sales': 120},
  {'region': 'North', 'month': 'Feb', 'sales': 135},
  {'region': 'North', 'month': 'Mar', 'sales': 98},
  {'region': 'South', 'month': 'Jan', 'sales': 85},
  {'region': 'South', 'month': 'Feb', 'sales': 92},
  {'region': 'South', 'month': 'Mar', 'sales': 110},
  {'region': 'West', 'month': 'Jan', 'sales': 165},
  {'region': 'West', 'month': 'Feb', 'sales': 140},
  {'region': 'West', 'month': 'Mar', 'sales': 180},
];

CristalyseChart()
  .data(performanceData)
  .mappingHeatMap(x: 'month', y: 'region', value: 'sales')
  .geomHeatMap(
    cellSpacing: 2.0,
    cellBorderRadius: BorderRadius.circular(4),
    showValues: true,
    // Specify custom gradient or omit for default GradientColorScale.heatMap()
    colorGradient: [Colors.lightBlue.shade100, Colors.blue.shade800],
    interpolateColors: true,
  )
  .scaleXOrdinal()
  .scaleYOrdinal()
  .theme(ChartTheme.defaultTheme())
  .build()
```

## Business Performance Heat Map

Monitor regional sales performance across months:

```dart theme={null}
final businessData = [
  {'region': 'North America', 'month': 'Q1', 'sales': 450},
  {'region': 'North America', 'month': 'Q2', 'sales': 520},
  {'region': 'North America', 'month': 'Q3', 'sales': 380},
  {'region': 'North America', 'month': 'Q4', 'sales': 620},
  {'region': 'Europe', 'month': 'Q1', 'sales': 320},
  {'region': 'Europe', 'month': 'Q2', 'sales': 290},
  {'region': 'Europe', 'month': 'Q3', 'sales': 410},
  {'region': 'Europe', 'month': 'Q4', 'sales': 480},
  {'region': 'Asia Pacific', 'month': 'Q1', 'sales': 180},
  {'region': 'Asia Pacific', 'month': 'Q2', 'sales': 220},
  {'region': 'Asia Pacific', 'month': 'Q3', 'sales': 280},
  {'region': 'Asia Pacific', 'month': 'Q4', 'sales': 350},
];

CristalyseChart()
  .data(businessData)
  .mappingHeatMap(x: 'month', y: 'region', value: 'sales')
  .geomHeatMap(
    cellSpacing: 2.0,
    cellBorderRadius: BorderRadius.circular(6),
    showValues: true,
    colorGradient: [Colors.red.shade200, Colors.orange, Colors.green.shade600],
    interpolateColors: true,
    valueFormatter: (value) => '\$${value.toStringAsFixed(0)}K',
    valueTextStyle: TextStyle(
      fontSize: 12,
      fontWeight: FontWeight.w600,
    ),
  )
  .scaleXOrdinal()
  .scaleYOrdinal()
  .theme(ChartTheme.defaultTheme())
  .build()
```

## System Monitoring Heat Map

Visualize server response times across hours and services:

```dart theme={null}
final monitoringData = [
  {'hour': '00:00', 'service': 'API Gateway', 'responseTime': 45},
  {'hour': '00:00', 'service': 'Auth Service', 'responseTime': 32},
  {'hour': '00:00', 'service': 'Database', 'responseTime': 28},
  {'hour': '06:00', 'service': 'API Gateway', 'responseTime': 120},
  {'hour': '06:00', 'service': 'Auth Service', 'responseTime': 85},
  {'hour': '06:00', 'service': 'Database', 'responseTime': 95},
  {'hour': '12:00', 'service': 'API Gateway', 'responseTime': 200},
  {'hour': '12:00', 'service': 'Auth Service', 'responseTime': 150},
  {'hour': '12:00', 'service': 'Database', 'responseTime': 180},
  {'hour': '18:00', 'service': 'API Gateway', 'responseTime': 180},
  {'hour': '18:00', 'service': 'Auth Service', 'responseTime': 130},
  {'hour': '18:00', 'service': 'Database', 'responseTime': 160},
];

CristalyseChart()
  .data(monitoringData)
  .mappingHeatMap(x: 'hour', y: 'service', value: 'responseTime')
  .geomHeatMap(
    cellSpacing: 1.0,
    cellBorderRadius: BorderRadius.circular(2),
    showValues: true,
    minValue: 0,
    maxValue: 250,
    colorGradient: [
      Colors.green.shade400,
      Colors.yellow,
      Colors.red.shade600,
    ],
    interpolateColors: true,
    nullValueColor: Colors.grey.shade300,
    valueFormatter: (value) => '${value.toInt()}ms',
    valueTextStyle: TextStyle(
      fontSize: 10,
      fontWeight: FontWeight.w600,
      color: Colors.white,
    ),
  )
  .scaleXOrdinal()
  .scaleYOrdinal()
  .theme(ChartTheme.darkTheme())
  .build()
```

## Correlation Matrix Heat Map

Display statistical correlations with diverging color scheme:

```dart theme={null}
final correlationData = [
  {'var1': 'Revenue', 'var2': 'Marketing', 'correlation': 0.85},
  {'var1': 'Revenue', 'var2': 'Sales Team', 'correlation': 0.92},
  {'var1': 'Revenue', 'var2': 'Customer Sat', 'correlation': 0.74},
  {'var1': 'Marketing', 'var2': 'Revenue', 'correlation': 0.85},
  {'var1': 'Marketing', 'var2': 'Sales Team', 'correlation': 0.68},
  {'var1': 'Marketing', 'var2': 'Customer Sat', 'correlation': 0.45},
  {'var1': 'Sales Team', 'var2': 'Revenue', 'correlation': 0.92},
  {'var1': 'Sales Team', 'var2': 'Marketing', 'correlation': 0.68},
  {'var1': 'Sales Team', 'var2': 'Customer Sat', 'correlation': 0.58},
  {'var1': 'Customer Sat', 'var2': 'Revenue', 'correlation': 0.74},
  {'var1': 'Customer Sat', 'var2': 'Marketing', 'correlation': 0.45},
  {'var1': 'Customer Sat', 'var2': 'Sales Team', 'correlation': 0.58},
];

CristalyseChart()
  .data(correlationData)
  .mappingHeatMap(x: 'var1', y: 'var2', value: 'correlation')
  .geomHeatMap(
    cellSpacing: 2.0,
    cellBorderRadius: BorderRadius.circular(3),
    showValues: true,
    minValue: -1.0,
    maxValue: 1.0,
    // Diverging gradient: negative (blue) → neutral (white) → positive (red)
    colorGradient: [
      Colors.blue.shade700,
      Colors.white,
      Colors.red.shade700,
    ],
    interpolateColors: true,
    valueFormatter: (value) => value.toStringAsFixed(2),
    valueTextStyle: TextStyle(fontSize: 11),
    cellAspectRatio: 1.0, // Square cells
  )
  .scaleXOrdinal()
  .scaleYOrdinal()
  .theme(ChartTheme.defaultTheme())
  .build()
```

## Styling Options

### Color Gradients

Define custom color schemes for different data types:

```dart theme={null}
// Single color gradient (low to high)
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap(
    colorGradient: [Colors.white, Colors.deepPurple],
    interpolateColors: true,
  )
  .build()

// Multi-step gradient
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap(
    colorGradient: [
      Colors.blue.shade900,
      Colors.blue.shade300,
      Colors.white,
      Colors.orange.shade300,
      Colors.red.shade900,
    ],
    interpolateColors: true,
  )
  .build()

// Diverging gradient
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap(
    colorGradient: [Colors.blue, Colors.white, Colors.red],
    interpolateColors: true,
  )
  .build()
```

### Cell Styling

Customize cell appearance and borders:

```dart theme={null}
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap(
    cellSpacing: 3.0,
    cellBorderRadius: BorderRadius.circular(8),
    cellAspectRatio: 1.5, // width:height ratio
    showValues: true,
  )
  .build()
```

### Value Text Styling

Control value text appearance:

```dart theme={null}
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap(
    showValues: true,
    valueTextStyle: TextStyle(
      fontSize: 14,
      fontWeight: FontWeight.bold,
      color: Colors.black87,
    ),
  )
  .build()
```

## Data Handling

### Missing Values

Handle null or missing data points:

```dart theme={null}
CristalyseChart()
  .data(dataWithNulls)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap(
    nullValueColor: Colors.grey.shade200,
  )
  .build()
```

### Value Ranges

Set explicit minimum and maximum values:

```dart theme={null}
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap(
    minValue: 0,
    maxValue: 100,
    // values outside range are clamped
    colorGradient: [Colors.white, Colors.red],
    interpolateColors: true,
  )
  .build()
```

### Value Formatting

Customize how values are displayed:

```dart theme={null}
import 'package:intl/intl.dart';

// Currency formatting
CristalyseChart()
  .data(salesData)
  .mappingHeatMap(x: 'month', y: 'region', value: 'revenue')
  .geomHeatMap(
    showValues: true,
    valueFormatter: (value) => NumberFormat.simpleCurrency().format(value),
  )
  .build()

// Percentage formatting
CristalyseChart()
  .data(percentageData)
  .mappingHeatMap(x: 'category', y: 'segment', value: 'percentage')
  .geomHeatMap(
    showValues: true,
    valueFormatter: (value) => '${(value * 100).toStringAsFixed(1)}%',
  )
  .build()

// Custom formatting
CristalyseChart()
  .data(temperatureData)
  .mappingHeatMap(x: 'hour', y: 'day', value: 'temperature')
  .geomHeatMap(
    showValues: true,
    valueFormatter: (value) => '${value.toStringAsFixed(1)}°C',
  )
  .build()
```

## Interactive Features

### Hover Effects

Add rich tooltips on cell hover:

```dart theme={null}
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap()
  .interaction(
    tooltip: TooltipConfig(
      builder: (point) {
        return Container(
          padding: EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.8),
            borderRadius: BorderRadius.circular(6),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                '${point.getDisplayValue('x')} - ${point.getDisplayValue('y')}',
                style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                ),
              ),
              Text(
                'Value: ${point.getDisplayValue('value')}',
                style: TextStyle(color: Colors.white),
              ),
            ],
          ),
        );
      },
    ),
  )
  .build()
```

### Click Handlers

React to cell selection:

```dart theme={null}
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap()
  .interaction(
    click: ClickConfig(
      onTap: (point) {
        print('Clicked cell: ${point.data}');
        // Show detailed view
        showCellDetails(point.data);
      },
    ),
  )
  .build()
```

## Animation Options

### Fade In Animation

Cells appear with smooth fade transition:

```dart theme={null}
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap()
  .animate(
    duration: Duration(milliseconds: 1000),
    curve: Curves.easeInOut,
  )
  .build()
```

### Staggered Animation

Each cell animates with a slight delay:

```dart theme={null}
CristalyseChart()
  .data(data)
  .mappingHeatMap(x: 'x', y: 'y', value: 'value')
  .geomHeatMap()
  .animate(
    duration: Duration(milliseconds: 1500),
    curve: Curves.elasticOut,
    stagger: Duration(milliseconds: 50),
  )
  .build()
```

## Best Practices

### When to Use Heat Maps

<Icon icon="check" /> **Good for:**

* 2D categorical data visualization
* Correlation matrices
* Time-based patterns (hour vs day)
* Geographic data on grids
* Performance monitoring dashboards

<Icon icon="x" /> **Avoid for:**

* Continuous spatial data
* Data with more than 20x20 cells
* Precise value comparison
* Single-dimension data

### Design Tips

* Use intuitive color schemes (cool to warm for intensity)
* Ensure sufficient color contrast for accessibility
* Limit grid size to maintain readability
* Consider showing values for precise reading
* Use diverging colors for data with meaningful zero point

### Performance Considerations

* Optimize for datasets with \< 400 cells (20x20)
* Use simpler styling for large grids
* Consider data aggregation for very large datasets
* Test color schemes for colorblind accessibility

## Common Patterns

### Website Analytics Heat Map

```dart theme={null}
final analyticsData = [
  {'page': 'Home', 'hour': '9 AM', 'visitors': 245},
  {'page': 'Home', 'hour': '12 PM', 'visitors': 380},
  {'page': 'Home', 'hour': '6 PM', 'visitors': 520},
  {'page': 'Products', 'hour': '9 AM', 'visitors': 180},
  {'page': 'Products', 'hour': '12 PM', 'visitors': 290},
  {'page': 'Products', 'hour': '6 PM', 'visitors': 350},
];

CristalyseChart()
  .data(analyticsData)
  .mappingHeatMap(x: 'hour', y: 'page', value: 'visitors')
  .geomHeatMap(
    cellSpacing: 2.0,
    showValues: true,
    colorGradient: [Colors.blue.shade100, Colors.blue.shade800],
    interpolateColors: true,
  )
  .build()
```

### Financial Risk Matrix

```dart theme={null}
final riskData = [
  {'probability': 'Low', 'impact': 'Low', 'risk': 1},
  {'probability': 'Low', 'impact': 'Medium', 'risk': 2},
  {'probability': 'Low', 'impact': 'High', 'risk': 3},
  {'probability': 'Medium', 'impact': 'Low', 'risk': 2},
  {'probability': 'Medium', 'impact': 'Medium', 'risk': 4},
  {'probability': 'Medium', 'impact': 'High', 'risk': 6},
  {'probability': 'High', 'impact': 'Low', 'risk': 3},
  {'probability': 'High', 'impact': 'Medium', 'risk': 6},
  {'probability': 'High', 'impact': 'High', 'risk': 9},
];

CristalyseChart()
  .data(riskData)
  .mappingHeatMap(x: 'probability', y: 'impact', value: 'risk')
  .geomHeatMap(
    cellSpacing: 2.0,
    cellAspectRatio: 1.25,
    showValues: true,
    colorGradient: [Colors.green, Colors.yellow, Colors.red],
    interpolateColors: true,
  )
  .build()
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Scatter Plots" icon="chart-scatter" href="/charts/scatter-plots">
    Explore relationships between continuous variables
  </Card>

  <Card title="Interactions" icon="hand-pointer" href="/features/interactions">
    Add advanced interactive features to charts
  </Card>

  <Card title="Theming" icon="palette" href="/features/theming">
    Customize colors and styling themes
  </Card>

  <Card title="Export" icon="download" href="/features/export">
    Save heat maps as images or data files
  </Card>
</CardGroup>
