热力图组件

一个直观展示数据密度和分布的热力图组件,支持多种颜色主题和交互功能

组件简介

热力图组件是一种数据可视化工具,通过颜色的深浅来直观地展示数据的密度和分布情况。本组件适用于展示用户活动、数据热点、时间序列数据等场景,如GitHub贡献图、网站访问热图、天气温度分布等。组件支持多种颜色主题、响应式设计和交互功能,帮助用户更直观地理解数据模式和趋势。

组件特性

  • 支持多种颜色主题(蓝色、红色、绿色、紫色等)
  • 响应式设计,适配不同屏幕尺寸
  • 交互式体验,支持悬停查看详细数据
  • 可自定义网格大小和单元格尺寸
  • 支持图例显示,方便用户理解数据含义
  • 简洁的API接口,易于集成和扩展
  • 基于CSS Grid布局,性能优良

基本使用

以下是一个基本的热力图组件示例,展示了默认蓝色主题的热力图效果:

最低
最高

高级示例

以下是几个不同场景下的热力图应用示例:

多种主题热力图

红色主题

绿色主题

紫色主题

自定义数据分布

集中式数据分布

HTML结构
<div class="heatmap-container heatmap-blue">
    <div class="heatmap-controls">
        <div class="control-group">
            <label for="themeSelect">选择主题:</label>
            <select id="themeSelect">
                <option value="blue">蓝色主题</option>
                <option value="red">红色主题</option>
                <option value="green">绿色主题</option>
                <option value="purple">紫色主题</option>
            </select>
        </div>
    </div>
    
    <div class="heatmap-wrapper">
        <div class="heatmap-grid"></div>
        <div class="heatmap-tooltip"></div>
    </div>
    
    <div class="heatmap-legend">
        <div class="legend-item">
            <span class="legend-color heatmap-cell-0"></span>
            <span>最低</span>
        </div>
        <!-- 更多图例项... -->
    </div>
</div>
JavaScript实现
// 热力图组件类
class Heatmap {
    constructor(containerId, options = {}) {
        this.container = document.getElementById(containerId);
        this.gridElement = this.container.querySelector('.heatmap-grid');
        this.tooltip = this.container.querySelector('.heatmap-tooltip');
        
        this.options = { ...this.defaultOptions, ...options };
        this.init();
    }
    
    defaultOptions = {
        theme: 'blue',
        gridSize: 52,
        cellSize: 12,
        generateRandomData: true
    };
    
    init() {
        this.render();
        this.bindEvents();
    }
    
    render() {
        // 清空现有网格
        this.gridElement.innerHTML = '';
        
        // 设置网格样式
        this.gridElement.style.gridTemplateColumns = `repeat(${this.options.gridSize}, ${this.options.cellSize}px)`;
        
        // 生成数据
        const data = this.generateData();
        
        // 渲染单元格
        data.forEach((value, index) => {
            const cell = document.createElement('div');
            cell.classList.add('heatmap-cell');
            cell.classList.add(`heatmap-cell-${value}`);
            
            // 为每个单元格存储数据值
            cell.dataset.value = value;
            
            this.gridElement.appendChild(cell);
        });
    }
    
    generateData() {
        const data = [];
        const totalCells = this.options.gridSize * this.options.gridSize;
        
        for (let i = 0; i < totalCells; i++) {
            if (this.options.generateRandomData) {
                // 生成随机数据
                data.push(Math.floor(Math.random() * 8));
            } else if (this.options.customData) {
                // 使用自定义数据
                data.push(this.options.customData[i] || 0);
            } else {
                data.push(0);
            }
        }
        
        return data;
    }
    
    bindEvents() {
        // 如果有工具提示,绑定鼠标事件
        if (this.tooltip) {
            const cells = this.gridElement.querySelectorAll('.heatmap-cell');
            
            cells.forEach(cell => {
                cell.addEventListener('mouseenter', (e) => {
                    const value = cell.dataset.value;
                    this.tooltip.textContent = `值: ${value}`;
                    this.tooltip.style.left = `${e.pageX + 10}px`;
                    this.tooltip.style.top = `${e.pageY - 30}px`;
                    this.tooltip.style.opacity = '1';
                });
                
                cell.addEventListener('mouseleave', () => {
                    this.tooltip.style.opacity = '0';
                });
            });
        }
    }
    
    // 更改主题
    setTheme(theme) {
        // 移除所有主题类
        this.container.classList.remove('heatmap-blue', 'heatmap-red', 'heatmap-green', 'heatmap-purple');
        // 添加新主题类
        this.container.classList.add(`heatmap-${theme}`);
        this.options.theme = theme;
    }
    
    // 更改网格大小
    setGridSize(size) {
        this.options.gridSize = size;
        this.render();
    }
}

// 初始化热力图
document.addEventListener('DOMContentLoaded', function() {
    const basicHeatmap = new Heatmap('basicHeatmap');
    
    // 主题切换
    document.getElementById('themeSelect').addEventListener('change', function(e) {
        basicHeatmap.setTheme(e.target.value);
    });
    
    // 网格大小切换
    document.getElementById('gridSizeSelect').addEventListener('change', function(e) {
        basicHeatmap.setGridSize(parseInt(e.target.value));
    });
    
    // 初始化其他示例热力图
    new Heatmap('redThemeGrid', { theme: 'red' });
    new Heatmap('greenThemeGrid', { theme: 'green' });
    new Heatmap('purpleThemeGrid', { theme: 'purple' });
    
    // 自定义数据分布
    const customData = generateConcentratedData(52);
    new Heatmap('customDataGrid', { customData: customData, generateRandomData: false });
    
    // 生成集中式数据分布
    function generateConcentratedData(size) {
        const data = [];
        const center = Math.floor(size / 2);
        
        for (let y = 0; y < size; y++) {
            for (let x = 0; x < size; x++) {
                const distance = Math.sqrt(Math.pow(x - center, 2) + Math.pow(y - center, 2));
                // 中心区域数值较高,向外逐渐降低
                const value = Math.max(0, Math.min(7, 7 - Math.floor(distance / 2)));
                data.push(value);
            }
        }
        
        return data;
    }
});

使用指南

以下是如何在您的项目中集成和使用热力图组件的步骤:

  1. 引入CSS文件:heatmap.css文件添加到您的项目中,并在HTML文件中引入。
  2. 创建HTML结构:使用示例中的HTML结构创建热力图容器。
  3. 初始化组件:使用JavaScript创建Heatmap类的实例,并根据需要配置选项。
  4. 自定义配置:您可以通过options对象自定义热力图的主题、网格大小、单元格尺寸等属性。
  5. 数据绑定:您可以提供自定义数据数组,或者使用组件自动生成的随机数据。
  6. 事件处理:组件内置了基本的交互事件,您也可以根据需要添加自定义事件处理器。

主题定制

热力图组件支持通过CSS自定义颜色主题。要创建新的主题,您只需要在CSS中定义相应的颜色类:

自定义主题CSS
/* 自定义橙色主题 */
.heatmap-orange .heatmap-cell-0 { background-color: #fff8eb; }
.heatmap-orange .heatmap-cell-1 { background-color: #ffe8c3; }
.heatmap-orange .heatmap-cell-2 { background-color: #ffd699; }
.heatmap-orange .heatmap-cell-3 { background-color: #ffc166; }
.heatmap-orange .heatmap-cell-4 { background-color: #ffad33; }
.heatmap-orange .heatmap-cell-5 { background-color: #ff9a00; }
.heatmap-orange .heatmap-cell-6 { background-color: #e68a00; }
.heatmap-orange .heatmap-cell-7 { background-color: #cc7a00; }