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"} } } } ] }
问题分析
- 详情文本位置错误:你设置的详情文本y坐标为
"-150",这个位置在画布可见区域之外,导致即使信号生效也看不到文本。 - 信号定义冗余:
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
相关产品推荐
相关产品推荐

