我有很多样地,每个样地都有很多样地。我需要放大和平移所有的图。此外,所有范围必须实时同步。如果我共享一个范围,在一些图中效果很好,但是对于许多图则会变得滞后。然后,为了解决这个问题,我想在平移或缩放操作完成时触发同步。在
当用户停止平移时,会触发一个PanEnd
事件。但是我不能对滚轮缩放做同样的操作,因为没有MouseWheelEnd
事件,只有一个MouseWheel
事件,所以我无法检测用户何时停止。最后,我添加了一个定期回调来不时更新范围。但我不喜欢这个解决方案。在
我也尝试过LODStart
和loend事件(与下采样相关),我不得不强制lod_threshold=1
。但有时LODEnd
不被触发,只有{
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource, CDSView
from bokeh.models.filters import IndexFilter
from bokeh.models.markers import Scatter, Circle
from bokeh.models.tools import LassoSelectTool
from bokeh.models.ranges import DataRange1d
from bokeh.plotting import curdoc, gridplot
from bokeh.events import MouseWheel, PanEnd
import numpy as np
N = 3500
x = np.random.random(size=N) * 200
y = np.random.random(size=N) * 200
source = ColumnDataSource(data=dict(x=x, y=y))
plots = []
x_ranges = []
y_ranges = []
p_last_modified = -1
def render_plot(i, p_last_modified):
range_padding = 0.25
x_range = DataRange1d(
range_padding=range_padding,
renderers=[]
)
y_range = DataRange1d(
range_padding=range_padding,
renderers=[]
)
plot = figure(
width=500,
height=500,
x_range=x_range,
y_range=y_range,
toolbar_location='left',
tools='pan,wheel_zoom,tap,lasso_select',
output_backend='webgl',
)
c = plot.scatter(
x='x',
y='y',
size=3,
fill_color='blue',
line_color=None,
line_alpha=1.0,
source=source,
nonselection_fill_color='blue',
nonselection_line_color=None,
nonselection_fill_alpha=1.0,
)
c.selection_glyph = Scatter(
fill_color='yellow',
line_color='red',
line_alpha=1.0,
)
def mouse_wheel_event(event):
print('>> MOUSE WHEEL EVENT: PLOT NUMBER: {}'.format(i))
global p_last_modified
p_last_modified = i
plot.on_event(MouseWheel, mouse_wheel_event)
def pan_end_event(event):
print('>> PAN END: {}'.format(i))
for p in range(len(plots)):
if p != i:
plots[p].x_range.end = plots[i].x_range.end
plots[p].x_range.start = plots[i].x_range.start
plots[p].y_range.end = plots[i].y_range.end
plots[p].y_range.start = plots[i].y_range.start
plot.on_event(PanEnd, pan_end_event)
plots.append(plot)
x_ranges.append(x_range)
y_ranges.append(y_range)
for i in range(12):
render_plot(i, p_last_modified)
gp = gridplot(
children=plots,
ncols=4,
plot_width=300,
plot_height=300,
toolbar_location='left',
)
def callback():
global p_last_modified
print('-- CALLBACK: last_modified: {}'.format(p_last_modified))
if p_last_modified != -1:
for p in range(len(plots)):
if p != p_last_modified:
plots[p].x_range.end = plots[p_last_modified].x_range.end
plots[p].x_range.start = plots[p_last_modified].x_range.start
plots[p].y_range.end = plots[p_last_modified].y_range.end
plots[p].y_range.start = plots[p_last_modified].y_range.start
p_last_modified = -1
curdoc().add_periodic_callback(callback, 3000)
curdoc().add_root(gp)
还有其他建议吗?在
虽然我不太喜欢,但我还是成功了。 它涉及一些JS和3个“虚拟”小部件,我希望有一种更简单的方法,但无论如何,这是一种方法。在
dum_txt_timer
是将用作计时器的文本输入,其值以秒为单位,并将使用所需的时间步长进行更新。当该值达到所需阈值时,将触发范围更新。当值低于阈值时,它什么也不做dum_button
是一个做两件事的按钮,第一次单击将启动dum_txt_timer
中的计时器,第二次单击将停止计时器。在dum_txt_trigger
是另一个文本输入,用于单击dum_button
并启动/停止计时器。在mouse_wheel_event
函数在鼠标滚轮的每次迭代中都会触发。鼠标所在绘图的值存储在mod_source
中,这是一个传递给dum_txt_timer
回调的数据源。 它检查dum_txt_timer
值是否为0,如果是,它会更新dum_txt_trigger
中的值,该值单击按钮并启动计时器,并更新dum\dum_txt_timer
的回调需要dum_txt_trigger
,即存储绘图ID和所有绘图范围的mod_source
数据源。 在timeout函数结束时更新dum_txt_timer
值之前,回调不执行任何操作。否则,它首先更新dum_txt_trigger
的值,该值第二次单击dum_button
,并停止计时器(将其重置为0。然后更新所有绘图的范围。在在这个例子中,更新之前的时间是由按钮回调中的timeout函数设置的。在
一件好事是,相同的虚拟小部件可以用于设置来自不同事件的范围更新的延迟,事件回调只需要更新
dum_txt_trigger
,就像mouse_wheel_event
相关问题 更多 >
编程相关推荐