使用前端访问绑定到散景字形的数据 javascript

Access data bound to Bokeh glyphs using front end javascript

我正在尝试将我的每个字形与一个 ID 相关联,然后在单击按钮时获取所选字形 ID 的列表。我需要将 ID 列表与页面上的一些其他用户输入相结合,因此使用 python 回调效果不佳。

到目前为止,我已经成功地通过 ColumnDataSource 传递了我的 ID(我没有找到仅使用 patches 方法的方法),但我不确定如何获取关联的 ID使用已选择的字形。

注意 ColumnDataSource 的 glyph_id 字段

from bokeh.plotting import figure, output_file, show
from bokeh.models import ColumnDataSource
from bokeh.models.glpyhs import Patches

output_file("patch.html")

plot = figure(tools="tap", plot_width=400, plot_height=400)
source = ColumnDataSource(dict(
    xs = [[1, 3, 2], [3, 4, 6, 6]],
    ys = [[2, 1, 4], [4, 7 , 8, 5]],
    glyph_id = [1, 2]
))

patches = Patches(xs="xs", ys="ys")
plot.add_glyph(source, patches)

show(plot)

编辑:

这是一个使用回调的解决方案,但有很多问题,主要问题是它会在每次点击事件时更新列表,而不是在我需要时简单地获取列表。

source.callback = CustomJS(code="""
    var selected_glyphs = cb_obj['selected']['1d']['indices'];
    var glyph_ids = cb_obj['data']['glyph_id']
    window.selected_glyphs = [];
    selected_glyphs.forEach(function(idx) {
        window.selected_glyphs.push(glyph_ids[idx]);
    });
""")

下面的示例仅在按下按钮时从数据源中检索当前选择,这似乎是您所要求的(仍然不是 100% 确定)。它还展示了如何将 patches 与明确提供的数据源一起使用。

from bokeh.layouts import column
from bokeh.models import Button, ColumnDataSource, CustomJS
from bokeh.plotting import figure, output_file, show

output_file("patch.html")

source = ColumnDataSource(dict(
    xs = [[1, 3, 2], [3, 4, 6, 6]],
    ys = [[2, 1, 4], [4, 7 , 8, 5]],
    id = [1, 2]
))

plot = figure(tools="tap", plot_width=400, plot_height=400)
plot.patches('xs', 'ys', source=source)

callback=CustomJS(args=dict(source=source), code="""
    var result = [];
    var selected = source.selected['1d'].indices;
    selected.forEach(function(idx) {
        result.push(source.data.id[idx]);
    });
    alert(result);
""")

button = Button(label='Make Selection and Press Me', callback=callback)

show(column(button, plot))

这是一个函数,用于获取使用 selected 的模型的句柄。使用 ColumnDataSource 获取任何模型句柄的更通用的方法可能是用 "column_names" 替换 "selected",但我还没有测试过。

var models = [];
for (var idx in Bokeh.index)
{
    if (Bokeh.index.hasOwnProperty(idx))
    {
        var idx_models = Bokeh.index[idx].model.document._all_models
        for (var model in idx_models)
        {
            if (idx_models.hasOwnProperty(model) && idx_models[model].attributes.hasOwnProperty("selected"))
                models.push(idx_models[model]);
        }
    }
}

以下是我实际完成特定事件的方式:

<button id="get-glyph-ids">Get Glyph Ids</button>
<script>
    document.getElementById("get-glyph-ids").addEventListener("click", function() {
        var selectedGlyphIds = [];
        for (var idx in Bokeh.index)
        {
            if (Bokeh.index.hasOwnProperty(idx))
            {
                var idxModels = Bokeh.index[idx].model.document._all_models;
                for (var modelId in idxModels)
                {
                    if (idxModels.hasOwnProperty(modelId) && idxModels[modelId].attributes.hasOwnProperty("selected"))
                    {
                        var modelGlyphIds = idxModels[modelId].data.glyph_id;
                        idxModels[modelId].selected["1d"]["indices"].forEach(function(glyphIdx){
                            selectedGlyphIds.push(modelGlyphIds[glyphIdx]);
                        });
                    }
                }
            }
        }
        console.log(selectedGlyphIds);
    });
</script>