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

Vega中悬停Bar/Text标记时hoveredEventType信号无法触发问题排查

解决Vega悬停详情文本标记不生效的问题

你在Vega规范中定义了三个标记:柱状条(rect)、关联文本(text)、悬停详情文本,但悬停详情的文本始终无法显示,hoveredEventType信号似乎未触发,而hoveredBar和hoveredText信号可正常控制柱状条和关联文本的样式。

你的原始Vega规范如下:

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "The PM2.5 value of Beijing observed 15 keys, highlighting the keys when PM2.5 level is hazardous to human health. Data source https://chartaccent.github.io/chartaccent.html",
  "background": "white",
  "padding": 5,
  "height": 250,
  "width": 500,
  "autosize": {
    "type": "fit",
    "resize": true
  },
  "data": [
    {
      "name": "source",
      "values": [
        { "key": "TYPE 1", "doc_count": 113 },
        { "key": "TYPE 2", "doc_count": 32 }
      ]
    }
  ],
  "signals": [
    {
      "name": "hoveredBar",
      "value": null,
      "on": [
        {"events": "rect:mouseover", "update": "datum.key"},
        {"events": "rect:mouseout", "update": "null"}
      ]
    },
    {
      "name": "hoveredText",
      "value": null,
      "on": [
        {"events": "text:mouseover", "update": "datum.key"},
        {"events": "text:mouseout", "update": "null"}
      ]
    },
    {
      "name": "hoveredEventType",
      "value": null,
      "on": [
        {"events": "rect:mouseover", "update": "datum"},
        {"events": "rect:mouseout", "update": "null"},
        {"events": "text:mouseover", "update": "datum"},
        {"events": "text:mouseout", "update": "null"}
      ]
    }
  ],
  "scales": [
    {
      "name": "x",
      "type": "band",
      "domain": {"data": "source", "field": "key"},
      "range": "width",
      "paddingInner": 0.1,
      "paddingOuter": 0.2
    },
    {
      "name": "y",
      "type": "linear",
      "domain": {"data": "source", "field": "doc_count"},
      "range": "height",
      "nice": true
    }
  ],
  "marks": [
    {
      "type": "rect",
      "from": {"data": "source"},
      "encode": {
        "enter": {
          "x": {"scale": "x", "field": "key"},
          "width": {"scale": "x", "band": 0.8},
          "y": {"scale": "y", "field": "doc_count"},
          "y2": {"scale": "y", "value": 0},
          "fill": {"value": "#00afa4"},
          "opacity": {"value": 1}
        },
        "update": {
          "opacity": [
            {"test": "datum.key === hoveredBar || datum.key === hoveredText", "value": 0.7},
            {"value": 1}
          ]
        }
      }
    },
    {
      "type": "text",
      "from": {"data": "source"},
      "encode": {
        "enter": {
          "x": {"scale": "x", "field": "key", "band": 0.43},
          "y": {"scale": "y", "field": "doc_count", "offset": -10},
          "text": {"field": "key"},
          "align": {"value": "center"},
          "fill": {"value": "black"}
        },
        "update": {
          "fill": [
            {"test": "datum.key === hoveredBar || datum.key === hoveredText", "value": "#f05c3e"},
            {"value": "black"}
          ]
        }
      }
    },
    // Hovered EventType details mark
    {
      "type": "text",
      "encode": {
        "enter": {
          "x": {"signal": "width - 10"},
          "y": {"signal": "-150"},
          "text": {"signal": "hoveredEventType ? hoveredEventType.key + ': ' + hoveredEventType.doc_count : ''"},
          "align": {"value": "right"},
          "baseline": {"value": "bottom"},
          "fill": {"value": "#f05c3e"},
          "fontWeight": {"value": "bold"},
          "fontSize": {"value": 16}
        },
        "update": { 
          "fillOpacity": {"signal": "hoveredEventType ? 1 : 0"}
        }
      }
    }
  ]
}

问题分析

  1. 详情文本位置错误:你设置的详情文本y坐标为"-150",这个位置在画布可见区域之外,导致即使信号生效也看不到文本。
  2. 信号定义冗余:hoveredBar和hoveredText信号完全可以合并到hoveredEventType中,减少不必要的信号监听,同时避免逻辑分散。

修正方案

核心修改点:

  • 调整详情文本的y坐标到画布可见区域,比如设置为height - 20,放在画布底部右侧。
  • 移除冗余的hoveredBar和hoveredText信号,直接用hoveredEventType控制所有hover状态的样式。
  • 优化mark的update条件,通过hoveredEventType的key值判断当前元素是否被hover。

修正后的完整代码

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "The PM2.5 value of Beijing observed 15 keys, highlighting the keys when PM2.5 level is hazardous to human health. Data source https://chartaccent.github.io/chartaccent.html",
  "background": "white",
  "padding": 5,
  "height": 250,
  "width": 500,
  "autosize": {
    "type": "fit",
    "resize": true
  },
  "data": [
    {
      "name": "source",
      "values": [
        { "key": "TYPE 1", "doc_count": 113 },
        { "key": "TYPE 2", "doc_count": 32 }
      ]
    }
  ],
  "signals": [
    {
      "name": "hoveredEventType",
      "value": null,
      "on": [
        {"events": "rect:mouseover", "update": "datum"},
        {"events": "rect:mouseout", "update": "null"},
        {"events": "text:mouseover", "update": "datum"},
        {"events": "text:mouseout", "update": "null"}
      ]
    }
  ],
  "scales": [
    {
      "name": "x",
      "type": "band",
      "domain": {"data": "source", "field": "key"},
      "range": "width",
      "paddingInner": 0.1,
      "paddingOuter": 0.2
    },
    {
      "name": "y",
      "type": "linear",
      "domain": {"data": "source", "field": "doc_count"},
      "range": "height",
      "nice": true
    }
  ],
  "marks": [
    {
      "type": "rect",
      "name": "barMark",
      "from": {"data": "source"},
      "encode": {
        "enter": {
          "x": {"scale": "x", "field": "key"},
          "width": {"scale": "x", "band": 0.8},
          "y": {"scale": "y", "field": "doc_count"},
          "y2": {"scale": "y", "value": 0},
          "fill": {"value": "#00afa4"},
          "opacity": {"value": 1}
        },
        "update": {
          "opacity": [
            {"test": "hoveredEventType && datum.key === hoveredEventType.key", "value": 0.7},
            {"value": 1}
          ]
        }
      }
    },
    {
      "type": "text",
      "name": "labelMark",
      "from": {"data": "source"},
      "encode": {
        "enter": {
          "x": {"scale": "x", "field": "key", "band": 0.43},
          "y": {"scale": "y", "field": "doc_count", "offset": -10},
          "text": {"field": "key"},
          "align": {"value": "center"},
          "fill": {"value": "black"}
        },
        "update": {
          "fill": [
            {"test": "hoveredEventType && datum.key === hoveredEventType.key", "value": "#f05c3e"},
            {"value": "black"}
          ]
        }
      }
    },
    // Hovered EventType details mark
    {
      "type": "text",
      "encode": {
        "enter": {
          "x": {"signal": "width - 10"},
          "y": {"signal": "height - 20"},
          "text": {"signal": "hoveredEventType ? hoveredEventType.key + ': ' + hoveredEventType.doc_count : ''"},
          "align": {"value": "right"},
          "baseline": {"value": "bottom"},
          "fill": {"value": "#f05c3e"},
          "fontWeight": {"value": "bold"},
          "fontSize": {"value": 16}
        },
        "update": { 
          "fillOpacity": {"signal": "hoveredEventType ? 1 : 0"}
        }
      }
    }
  ]
}

说明

修正后,悬停柱状条或关联文本时,hoveredEventType会正确获取当前数据,详情文本会显示在画布底部右侧,同时柱状条和文本的样式也会按预期变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 22:37:03