You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于鼠标滚轮的2D热图幅值缩放实现需求

没问题!Matplotlib完全能搞定这个需求——只需要给热图所在的Axes绑定鼠标滚轮事件,就能实现滚动调节颜色幅值的缩放。下面分两种场景给你写好可直接运行的代码:

场景1:未指定Vmin/Vmax时的滚轮缩放

这种情况我们默认基于数据的原始极值(data.min()data.max())来动态调整缩放比例。每次滚轮滚动时,会以当前的vmin/vmax为基准,按比例放大或缩小范围:

import matplotlib.pyplot as plt
import numpy as np

# 生成测试数据
data = np.random.randn(50, 50)
data = data - data.min()  # 转成非负方便看效果

fig, ax = plt.subplots()
im = ax.imshow(data, cmap='viridis')
fig.colorbar(im)

# 定义滚轮缩放的比例因子(可根据需求调整灵敏度)
scale_factor = 1.1

def zoom_handler(event):
    # 只响应当前热图所在Axes的滚轮事件
    if event.inaxes != ax:
        return
    
    # 获取当前颜色范围
    current_vmin, current_vmax = im.get_clim()
    range_val = current_vmax - current_vmin
    
    if event.button == 'up':
        # 向上滚动:缩小颜色范围,增强对比度
        new_vmin = current_vmin + range_val * (1 - 1/scale_factor)/2
        new_vmax = current_vmax - range_val * (1 - 1/scale_factor)/2
    else:
        # 向下滚动:扩大颜色范围,减弱对比度,不超过数据原始极值
        new_vmin = max(current_vmin - range_val * (scale_factor - 1)/2, data.min())
        new_vmax = min(current_vmax + range_val * (scale_factor - 1)/2, data.max())
    
    # 更新颜色范围并刷新画布
    im.set_clim(new_vmin, new_vmax)
    fig.canvas.draw_idle()

# 绑定滚轮事件到画布
fig.canvas.mpl_connect('scroll_event', zoom_handler)

plt.show()
场景2:指定固定Vmin/Vmax后的滚轮缩放

如果已经提前设定了vmin和vmax(比如想在某个固定区间内缩放),我们可以以当前范围的中心为基准缩放上下限,同时保证不超出你设定的初始极值:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.randn(50, 50)
# 自定义初始颜色范围
initial_vmin = -2
initial_vmax = 2

fig, ax = plt.subplots()
im = ax.imshow(data, cmap='viridis', vmin=initial_vmin, vmax=initial_vmax)
fig.colorbar(im)

scale_factor = 1.1

def zoom_fixed_range_handler(event):
    if event.inaxes != ax:
        return
    
    current_vmin, current_vmax = im.get_clim()
    range_val = current_vmax - current_vmin
    center_val = (current_vmin + current_vmax) / 2
    
    if event.button == 'up':
        # 向上滚动:缩小范围,保持中心不变
        new_range = range_val / scale_factor
        new_vmin = center_val - new_range/2
        new_vmax = center_val + new_range/2
        # 限制在初始设定的极值内
        new_vmin = max(new_vmin, initial_vmin)
        new_vmax = min(new_vmax, initial_vmax)
    else:
        # 向下滚动:扩大范围,直到触达初始极值
        new_range = range_val * scale_factor
        new_vmin = center_val - new_range/2
        new_vmax = center_val + new_range/2
        new_vmin = max(new_vmin, initial_vmin)
        new_vmax = min(new_vmax, initial_vmax)
    
    im.set_clim(new_vmin, new_vmax)
    fig.canvas.draw_idle()

fig.canvas.mpl_connect('scroll_event', zoom_fixed_range_handler)

plt.show()
备选方案:用Plotly实现(更轻量化的交互)

如果你想要更开箱即用的交互体验,Plotly的热图自带基础缩放功能,要是需要自定义滚轮控制幅值,也可以用Dash回调实现:

import plotly.graph_objects as go
import numpy as np

data = np.random.randn(50, 50)
initial_vmin = -2
initial_vmax = 2

# 生成基础热图
fig = go.Figure(data=go.Heatmap(z=data, zmin=initial_vmin, zmax=initial_vmax, colorscale='Viridis'))

# 用Dash实现滚轮回调的框架(需要安装dash库)
# import dash
# from dash import dcc, html, Input, Output

# app = dash.Dash(__name__)
# app.layout = html.Div([dcc.Graph(id='heatmap', figure=fig)])

# @app.callback(
#     Output('heatmap', 'figure'),
#     Input('heatmap', 'relayoutData'),
#     prevent_initial_call=True
# )
# def update_zoom(relayoutData):
#     # 解析滚轮事件,参考Matplotlib的逻辑调整zmin/zmax
#     updated_fig = go.Figure(fig)
#     # 这里补充具体缩放逻辑
#     return updated_fig

# app.run_server(debug=True)

上面的Matplotlib代码直接运行就能看到效果,你可以根据自己的数据调整scale_factor来改变缩放的灵敏度~

内容的提问来源于stack exchange,提问作者Rafael Lainez

火山引擎 最新活动