You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Shiny for Python交互式绘图中识别选中/悬停的Ax?

Shiny for Python多子图交互:识别选中/悬停的Ax

1. 判断哪个Ax被选中(点击交互)

可以通过两种直接的方式实现:

  • 给Ax添加唯一标识:创建子图时为每个Ax设置自定义ID,比如ax.set_gid(f"subplot_{i}"),在点击回调中通过事件对象获取点击元素所属的Ax,进而拿到对应ID。
  • 坐标范围匹配:调用plt.gcf().get_axes()获取所有子图,通过每个Ax的get_window_extent()方法得到其像素范围,再结合点击事件的coords_css坐标,判断该坐标落在哪个Ax的范围内。

示例代码片段:

from matplotlib.pyplot import gcf

def on_click(event):
    for ax in gcf().get_axes():
        bbox = ax.get_window_extent()
        if bbox.contains(event.x, event.y):
            print(f"选中的子图:{ax.get_gid()}")
            break

2. 识别多子图中被悬停的Ax

针对你提到的悬停事件返回JSON缺少子图信息的问题,推荐两种简便方案:

方案一:为Ax添加唯一标识并关联交互元素

创建子图时给每个Ax分配唯一ID,同时给子图内的所有可交互元素(如线条、散点)设置gid属性关联到对应Ax的ID。在悬停回调中,通过事件数据中的元素gid直接匹配到对应的Ax。

示例代码:

fig, axes = plt.subplots(2, 2)
for i, ax in enumerate(axes.flat):
    ax_id = f"ax_{i}"
    ax.set_gid(ax_id)
    # 给子图内的绘图元素绑定相同ID
    line = ax.plot([1,2,3])[0]
    line.set_gid(ax_id)

方案二:预计算Ax像素范围并实时匹配

绘图完成后,获取每个Ax的get_window_extent()(包含相对于整个画布的像素坐标)并存储这些范围信息。在悬停回调中,用事件的coords_css.x和coords_css.y匹配到对应的Ax。

若窗口resize,需重新计算所有Ax的范围,可以监听窗口resize事件触发更新逻辑。

示例逻辑:

# 初始化时存储每个Ax的像素范围
ax_bboxes = []
fig, axes = plt.subplots(2, 2)
for ax in axes.flat:
    bbox = ax.get_window_extent()
    ax_bboxes.append({
        "ax": ax,
        "left": bbox.x0,
        "right": bbox.x1,
        "top": bbox.y0,
        "bottom": bbox.y1
    })

# 悬停回调中匹配子图
def on_hover(hover_data):
    css_x = hover_data["coords_css"]["x"]
    css_y = hover_data["coords_css"]["y"]
    for bbox_info in ax_bboxes:
        if (bbox_info["left"] <= css_x <= bbox_info["right"] 
            and bbox_info["top"] <= css_y <= bbox_info["bottom"]):
            print(f"悬停的子图:{bbox_info['ax'].get_gid()}")
            break

补充说明

你提供的悬停JSON中的range字段是子图自身的数据坐标范围,而coords_css是相对于图表容器的像素坐标,用coords_css匹配预存的Ax像素范围是更直接的方式。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 14:37:30