Dash中Plotly Treemap仅子容器显示Hover信息的实现问题
解决Dash中Treemap父容器悬停异常的两种方案
针对你遇到的Treemap父容器悬停格式异常问题,以下两种方案可直接在Dash回调返回figure的场景下实现需求:
方案一:完全禁用父容器的悬停效果
方法1:通过Trace属性直接控制
在生成Treemap时,针对父节点单独设置hoverinfo='none',子节点保留正常悬停配置。需要根据你的数据结构判断父节点(示例中以parents数组为空字符串作为父节点标识):
import plotly.graph_objects as go def update_treemap_figure(): # 假设你的数据定义如下 labels = ["A股总市值", "科技板块", "金融板块", "腾讯", "阿里", "工行", "招行"] parents = ["", "A股总市值", "A股总市值", "科技板块", "科技板块", "金融板块", "金融板块"] values = [500000, 200000, 300000, 120000, 80000, 180000, 120000] # 生成Treemap trace,为父节点设置hoverinfo为none fig = go.Figure(go.Treemap( labels=labels, parents=parents, values=values, # 动态设置每个节点的hoverinfo:父节点禁用,子节点正常显示 hoverinfo=[ 'none' if p == "" else 'label+value+percent parent' for p in parents ] )) return fig
方法2:通过PostScript前端控制
如果数据结构复杂,可在figure中添加PostScript代码,前端判断父节点并隐藏tooltip:
def update_treemap_figure(): labels = ["A股总市值", "科技板块", "金融板块", "腾讯", "阿里", "工行", "招行"] parents = ["", "A股总市值", "A股总市值", "科技板块", "科技板块", "金融板块", "金融板块"] values = [500000, 200000, 300000, 120000, 80000, 180000, 120000] fig = go.Figure(go.Treemap( labels=labels, parents=parents, values=values, hoverinfo='label+value+percent parent' )) # 添加PostScript实现父节点悬停禁用 fig.update_layout( post_script=f""" const treemap = document.querySelector('.treemap'); if (treemap) {{ treemap.addEventListener('mouseover', (e) => {{ const node = e.target.closest('.trace .treemap-node'); if (!node) return; const nodeIndex = parseInt(node.getAttribute('data-point-index')); const parents = {parents}; // 判断是否为父节点(根据你的数据逻辑调整) if (parents[nodeIndex] === "") {{ const tooltip = document.querySelector('.plotly-tooltip'); if (tooltip) tooltip.style.display = 'none'; }} }}); }} """ ) return fig
方案二:自定义父容器的悬停内容
方法1:生成Trace时自定义Hovertext
提前为父节点设置格式化的悬停文本,子节点保留原有逻辑:
def update_treemap_figure(): labels = ["A股总市值", "科技板块", "金融板块", "腾讯", "阿里", "工行", "招行"] parents = ["", "A股总市值", "A股总市值", "科技板块", "科技板块", "金融板块", "金融板块"] values = [500000, 200000, 300000, 120000, 80000, 180000, 120000] # 预计算父节点的汇总数据 parent_totals = {} # 计算根节点总价值 parent_totals[""] = sum(values) # 计算各子板块总价值 for parent in set(parents) - {""}: parent_totals[parent] = sum(v for l, p, v in zip(labels, parents, values) if p == parent) # 生成自定义hovertext hovertext = [] for l, p, v in zip(labels, parents, values): if p == "": # 根节点(父容器)的自定义悬停文本 hovertext.append(f"板块:{l}<br>总市值:{v}亿元<br>占全市场比例:{round(v/parent_totals['']*100, 2)}%") else: # 子节点的正常悬停文本 hovertext.append(f"股票:{l}<br>市值:{v}亿元<br>占板块比例:{round(v/parent_totals[p]*100, 2)}%") fig = go.Figure(go.Treemap( labels=labels, parents=parents, values=values, hovertext=hovertext, hoverinfo='text' # 使用自定义的hovertext )) return fig
方法2:通过PostScript修改Tooltip内容
在前端动态修改父节点的tooltip显示内容:
def update_treemap_figure(): labels = ["A股总市值", "科技板块", "金融板块", "腾讯", "阿里", "工行", "招行"] parents = ["", "A股总市值", "A股总市值", "科技板块", "科技板块", "金融板块", "金融板块"] values = [500000, 200000, 300000, 120000, 80000, 180000, 120000] parent_totals = {} parent_totals[""] = sum(values) for parent in set(parents) - {""}: parent_totals[parent] = sum(v for l, p, v in zip(labels, parents, values) if p == parent) fig = go.Figure(go.Treemap( labels=labels, parents=parents, values=values, hoverinfo='label+value+percent parent' )) fig.update_layout( post_script=f""" const treemap = document.querySelector('.treemap'); if (treemap) {{ treemap.addEventListener('mouseover', (e) => {{ const node = e.target.closest('.trace .treemap-node'); if (!node) return; const nodeIndex = parseInt(node.getAttribute('data-point-index')); const parents = {parents}; const labels = {labels}; const values = {values}; const parentTotals = {parent_totals}; if (parents[nodeIndex] === "") {{ const tooltip = document.querySelector('.plotly-tooltip'); if (tooltip) {{ tooltip.innerHTML = ` <div>板块:${labels[nodeIndex]}</div> <div>总市值:${values[nodeIndex]}亿元</div> <div>占全市场比例:${Math.round(values[nodeIndex]/parentTotals['']*100,2)}%</div> `; }} }} }}); }} """ ) return fig
注意事项
- 以上示例中判断父节点的逻辑(
parents[nodeIndex] === "")需根据你的实际数据结构调整,比如部分场景下父节点的parent字段为null或其他标识。 - PostScript方案需确保页面中Treemap的选择器(
.treemap)正确,若存在多个图表可通过data-div-id定位特定图表。
内容的提问来源于stack exchange,提问作者Satyajit Giram
相关产品推荐
相关产品推荐

