Hi! I am currently working on a project where i have two types of glyphs: routes (multiline) and nodes (circles). I would live to achive the following interactivity:
- When user clicks on a line all circles become selected.
- When user clics on a circle all lines will become selected.
I was able to achive first task, however when i try to solve 2nd task with a similiar js code iam able to update source_lines.selected.indices and emit changes to ColumnDataSource via emit() method in js, visually nothing changes. Could you please advise me on what iam missing. My minimum working example is bellow:
import bokeh
import bokeh.plotting
import bokeh.tile_providers
from bokeh.models import TapTool, ColumnDataSource, MultiLine, Circle
from bokeh.models.callbacks import CustomJS
tap = TapTool()
x_circle = [1, 2, 3, 4, 5]
y_cirlce = [6, 7, 2, 4, 5]
data = {'x': x_circle, 'y': y_cirlce}
circle_source = ColumnDataSource(data)
xs_lines = [[1, 3, 2], [3, 4, 6, 6]]
ys_lines = [[2, 1, 4], [4, 7, 8, 5]]
data = {'xs': xs_lines, 'ys': ys_lines}
lines_source = ColumnDataSource(data)
p = bokeh.plotting.figure(plot_width=1600, plot_height=1000,
tools=['pan', 'wheel_zoom', 'reset', tap], active_scroll='wheel_zoom')
circle_renderer = p.circle('x', 'y', source=circle_source, size=20, color="navy", alpha=0.5)
selected_circle= Circle(fill_color='black')
nonselected_circle = Circle(fill_alpha=0.6)
circle_renderer.selection_glyph = selected_circle
circle_renderer.nonselection_glyph = nonselected_circle
line_renderer = p.multi_line('xs', 'ys', source=lines_source, name='route',
line_color='blue', legend='routes', line_width=3)
selected_line = MultiLine(line_width=4, line_color='#f4aa42')
nonselected_line = MultiLine(line_alpha=0.4, line_color='#0000ff')
line_renderer.selection_glyph = selected_line
line_renderer.nonselection_glyph = nonselected_line
js_code = '''
// Get data from ColumnDataSource
if (source_circles.selected.indices.length > 0){
source_lines.selected.indices = [0, 1];
source_lines.change.emit();
console.log(source_lines.selected.indices)
} else if (source_lines.selected.indices.length > 0) {
source_circles.selected.indices = [0, 1, 2, 3, 4];
source_circles.change.emit();
console.log(source_circles.selected.indices)
}
'''
callback = CustomJS(args={'source_circles': circle_source,
'source_lines': lines_source}, code=js_code)
tap.callback = callback
bokeh.plotting.show(p)