阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 热力图(Heatmap)实现

热力图(Heatmap)实现

作者:陈川 阅读数:18510人阅读 分类: ECharts

热力图(Heatmap)实现

热力图是一种通过颜色变化展示数据密度的可视化方式,特别适合展示大量数据的分布规律。ECharts提供了强大的热力图组件,支持直角坐标系和地理坐标系两种形式,能够灵活应对不同场景的需求。

基本热力图配置

最简单的热力图只需要三个关键配置项:x轴、y轴和数据点。数据点需要包含x坐标、y坐标和值三个维度。以下是一个基础示例:

option = {
    tooltip: {},
    grid: {
        left: '3%',
        right: '7%',
        bottom: '3%',
        containLabel: true
    },
    xAxis: {
        type: 'category',
        data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    },
    yAxis: {
        type: 'category',
        data: ['早餐', '午餐', '晚餐', '夜宵']
    },
    visualMap: {
        min: 0,
        max: 10,
        calculable: true,
        orient: 'horizontal',
        left: 'center',
        bottom: '15%'
    },
    series: [{
        name: '用餐热度',
        type: 'heatmap',
        data: [
            [0, 0, 5],  // 周一早餐
            [0, 1, 7],  // 周一午餐
            [0, 2, 3],  // 周一晚餐
            [0, 3, 1],  // 周一夜宵
            // 其他数据...
            [6, 2, 8]   // 周日晚餐
        ],
        label: {
            show: true
        },
        emphasis: {
            itemStyle: {
                shadowBlur: 10,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
        }
    }]
};

数据格式处理

实际项目中,原始数据往往需要经过处理才能用于热力图展示。常见的数据转换方式包括:

  1. 从二维数组转换:
function convertToHeatmapData(matrix) {
    const result = [];
    for (let i = 0; i < matrix.length; i++) {
        for (let j = 0; j < matrix[i].length; j++) {
            result.push([i, j, matrix[i][j]]);
        }
    }
    return result;
}
  1. 从对象数组转换:
const rawData = [
    { day: '周一', meal: '早餐', value: 5 },
    { day: '周一', meal: '午餐', value: 7 },
    // ...
];

const xCategories = [...new Set(rawData.map(item => item.day))];
const yCategories = [...new Set(rawData.map(item => item.meal))];

const heatmapData = rawData.map(item => [
    xCategories.indexOf(item.day),
    yCategories.indexOf(item.meal),
    item.value
]);

视觉映射配置

visualMap组件控制如何将数据值映射到视觉元素(主要是颜色)。ECharts提供了多种视觉映射方式:

visualMap: {
    type: 'piecewise',  // 分段型
    pieces: [
        { min: 0, max: 3, label: '低', color: '#d94e5d' },
        { min: 3, max: 6, label: '中', color: '#eac736' },
        { min: 6, max: 10, label: '高', color: '#50a3ba' }
    ],
    orient: 'vertical',
    left: 'right',
    top: 'center'
}

或者使用连续型映射:

visualMap: {
    type: 'continuous',
    min: 0,
    max: 10,
    inRange: {
        color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
    }
}

地理热力图

ECharts支持在地图上展示热力图,特别适合展示地理分布数据:

$.get('geoJSON/China.json', function(geoJson) {
    echarts.registerMap('china', geoJson);
    
    const option = {
        tooltip: {
            trigger: 'item',
            formatter: '{b}: {c}'
        },
        visualMap: {
            min: 0,
            max: 1000,
            text: ['高', '低'],
            realtime: false,
            calculable: true,
            inRange: {
                color: ['#50a3ba', '#eac736', '#d94e5d']
            }
        },
        series: [{
            name: '销量',
            type: 'heatmap',
            coordinateSystem: 'geo',
            data: [
                {name: '北京', value: 923},
                {name: '上海', value: 865},
                // ...
            ],
            pointSize: 10,
            blurSize: 15
        }]
    };
    
    myChart.setOption(option);
});

性能优化技巧

当数据量较大时,热力图可能会出现性能问题。以下是一些优化建议:

  1. 使用渐进渲染:
series: [{
    progressive: 1000,
    progressiveThreshold: 10000
}]
  1. 降低数据精度:
function downsampleData(data, factor) {
    const result = [];
    for (let i = 0; i < data.length; i += factor) {
        result.push(data[i]);
    }
    return result;
}
  1. 调整热力点大小和模糊半径:
series: [{
    pointSize: 5,  // 较小的点
    blurSize: 8    // 适当的模糊半径
}]

交互功能增强

ECharts热力图支持丰富的交互功能:

  1. 数据筛选:
visualMap: {
    type: 'continuous',
    range: [3, 7],  // 只显示值在3-7之间的数据
    hoverLink: true  // 鼠标悬停时显示对应数据
}
  1. 区域缩放:
dataZoom: [
    {
        type: 'slider',
        xAxisIndex: 0,
        filterMode: 'filter'
    },
    {
        type: 'inside',
        xAxisIndex: 0,
        filterMode: 'filter'
    }
]
  1. 自定义提示框:
tooltip: {
    formatter: function(params) {
        return `${params.seriesName}<br/>
                ${params.data[0]}: ${params.data[1]}<br/>
                值: ${params.data[2]}`;
    }
}

高级应用示例

结合散点图的热力图,可以同时展示数据分布和具体数值:

series: [
    {
        name: '热力图',
        type: 'heatmap',
        data: heatmapData,
        emphasis: {
            itemStyle: {
                shadowBlur: 10,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
        }
    },
    {
        name: '散点',
        type: 'scatter',
        symbolSize: function(data) {
            return Math.sqrt(data[2]) * 5;
        },
        data: heatmapData.filter(item => item[2] > threshold),
        label: {
            show: true,
            formatter: function(params) {
                return params.data[2];
            }
        }
    }
]

动态数据更新

热力图支持动态数据更新,适合实时数据展示:

function updateHeatmap() {
    const newData = generateNewData();
    myChart.setOption({
        series: [{
            data: newData
        }]
    });
    
    // 更新visualMap范围
    const values = newData.map(item => item[2]);
    myChart.setOption({
        visualMap: {
            min: Math.min(...values),
            max: Math.max(...values)
        }
    });
}

setInterval(updateHeatmap, 2000);

自定义渲染效果

通过修改itemStyle可以实现各种自定义效果:

series: [{
    itemStyle: {
        borderColor: 'rgba(255, 255, 255, 0.8)',
        borderWidth: 1,
        shadowColor: 'rgba(0, 0, 0, 0.5)',
        shadowBlur: 10
    },
    blurSize: 5,
    pointSize: 15
}]

多热力图联动

多个热力图可以通过axisIndex实现联动:

grid: [
    {left: '5%', width: '40%', top: '10%', height: '80%'},
    {right: '5%', width: '40%', top: '10%', height: '80%'}
],
xAxis: [
    {gridIndex: 0, type: 'category', data: ['Q1', 'Q2', 'Q3', 'Q4']},
    {gridIndex: 1, type: 'category', data: ['A组', 'B组', 'C组', 'D组']}
],
yAxis: [
    {gridIndex: 0, type: 'category', data: ['北京', '上海', '广州', '深圳']},
    {gridIndex: 1, type: 'category', data: ['产品1', '产品2', '产品3']}
],
series: [
    {
        type: 'heatmap',
        data: data1,
        xAxisIndex: 0,
        yAxisIndex: 0
    },
    {
        type: 'heatmap',
        data: data2,
        xAxisIndex: 1,
        yAxisIndex: 1
    }
]

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌