如何用JS回调获取散点图索引?回调输出始终为undefined求排查
问题原因
你当前的代码里,tap事件本身不会自动选中散点,所以source.selected.indices是空数组,取索引[0]自然返回undefined。
解决方案
有两种可行的解决方式,根据你的需求选择:
方案一:用TapTool实现点击选中并获取索引
这种方式会让点击的点被标记为选中(默认带高亮效果),同时能拿到索引:
from bokeh.models import ColumnDataSource, CustomJS, TapTool from bokeh.plotting import figure, show # 构造数据源 source = ColumnDataSource(data=dict( x=[1, 2, 3, 4, 5], y=[6, 7, 8, 9, 10], color=["navy", "orange", "olive", "firebrick", "gold"] )) plot = figure() # 保存散点的渲染器对象 circle_renderer = plot.circle('x', 'y', size=10, source=source, color='color') # 编写回调逻辑,增加空值判断避免报错 callback = CustomJS(args=dict(source=source), code=""" var index = source.selected.indices[0]; if (index !== undefined) { alert(index); } """) # 创建TapTool,指定作用的渲染器和回调函数 tap_tool = TapTool(renderers=[circle_renderer], callback=callback) plot.add_tools(tap_tool) show(plot)
方案二:直接通过点击坐标计算对应点索引
这种方式不依赖选中状态,直接根据点击的坐标匹配最近的点,适合不需要选中视觉反馈的场景:
from bokeh.models import ColumnDataSource, CustomJS from bokeh.plotting import figure, show source = ColumnDataSource(data=dict( x=[1, 2, 3, 4, 5], y=[6, 7, 8, 9, 10], color=["navy", "orange", "olive", "firebrick", "gold"] )) plot = figure() plot.circle('x', 'y', size=10, source=source, color='color') # 利用tap事件的坐标信息计算目标点 callback = CustomJS(args=dict(source=source, plot=plot), code=""" // 将屏幕坐标转换为数据坐标 var x = plot.x_scale.invert(event.x); var y = plot.y_scale.invert(event.y); var data = source.data; var closestIndex = -1; var minDistance = Infinity; // 遍历所有点,找到距离点击位置最近的点 for (var i = 0; i < data.x.length; i++) { var dx = x - data.x[i]; var dy = y - data.y[i]; var distance = dx*dx + dy*dy; // 用平方距离替代开方,提升计算效率 if (distance < minDistance) { minDistance = distance; closestIndex = i; } } if (closestIndex !== -1) { alert(closestIndex); } """) plot.js_on_event('tap', callback) show(plot)
内容的提问来源于stack exchange,提问作者You Zou
相关产品推荐
相关产品推荐

