Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Bokeh:如何单击并拖动以显示点之间的位移_Python_Bokeh - Fatal编程技术网

Python Bokeh:如何单击并拖动以显示点之间的位移

Python Bokeh:如何单击并拖动以显示点之间的位移,python,bokeh,Python,Bokeh,我希望能够在图形上的两点之间单击并拖动,显示点之间位置的变化,并显示连接两点的线。我怎样才能接近这一点 您可以使用JS回调实现它,如下所示(Bokeh v1.3.0): 第一次单击绘图开始绘制线,下一次单击结束绘制线 或者,如果您更喜欢类似工具提示的div外观,您可以使用稍微复杂一点的代码,动态添加工具提示div: import numpy as np from bokeh.plotting import figure, show from bokeh.models import Column

我希望能够在图形上的两点之间单击并拖动,显示点之间位置的变化,并显示连接两点的线。我怎样才能接近这一点


您可以使用JS回调实现它,如下所示(Bokeh v1.3.0):

第一次单击绘图开始绘制线,下一次单击结束绘制线

或者,如果您更喜欢类似工具提示的div外观,您可以使用稍微复杂一点的代码,动态添加工具提示div:

import numpy as np
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.events import *

source = ColumnDataSource({'x': [], 'y': []})

p = figure(plot_width = 900)
lines = [p.line(np.arange(10), np.random.random(10)) for i in range(3)]
line = p.line('x', 'y', line_color = 'red', line_dash = 'dashed', source = source)

callback_tap = '''

if (typeof custom_tooltip == 'undefined') {
        custom_tooltip = document.createElement('div');
        custom_tooltip.setAttribute('id','tooltip_div');
        custom_tooltip.style = 'position: absolute; left: 0px; top: 0px; z-index: 9999; border:1px solid black; padding: 10px; background: white; font-family: arial; font-size: 12px'
        document.body.prepend(custom_tooltip);  
}        

if (true === Bokeh.drawing) {
    Bokeh.drawing = false
}
else {
    if (!Bokeh.drawing) {
        src.data = {'x':[], 'y':[]}        
        src.change.emit()
    }

    src.data['x'].push(cb_obj.x)
    src.data['y'].push(cb_obj.y)

    Bokeh.drawing = true
    Bokeh.sx_start = cb_obj.sx
    Bokeh.x_start = cb_obj.x
    Bokeh.sy_start = cb_obj.sy
    Bokeh.y_start = cb_obj.y  
}'''

callback_mousemove = '''
function print(...args) {
    for (i in args) {
        console.log(args[i])
    }
}

if (Bokeh.drawing) {  
    if (src.data['x'].length > 1) {
        src.data['x'].pop()
        src.data['y'].pop()   
    }

    src.data['x'].push(cb_obj.x)
    src.data['y'].push(cb_obj.y)
    src.change.emit()

    tooltip = document.getElementById('tooltip_div')
    tooltip.style.left = cb_obj.sx + 30 + 'px'
    tooltip.style.top = cb_obj.sy + 10 + 'px'
    tooltip.innerHTML = 'Distance X: ' + Math.round(cb_obj.sx - Bokeh.sx_start) + ' px' + ' (units): ' + (Math.round((cb_obj.x - Bokeh.x_start) * 100) / 100) + ' units' + 
                        '<br />' +
                        'Distance Y: ' + Math.round(cb_obj.sy - Bokeh.sy_start) + ' px' + ' (units): ' + (Math.round((cb_obj.y - Bokeh.y_start) * 100) / 100) + ' units' 

}'''

p.js_on_event('tap', CustomJS(args = {'src': source, }, code = callback_tap))
p.js_on_event('mousemove', CustomJS(args = {'src': source, }, code = callback_mousemove))

show(p)
将numpy导入为np
从bokeh.plotting导入图形,显示
从bokeh.models导入ColumnDataSource,CustomJS
从bokeh.events导入*
source=ColumnDataSource({'x':[],'y':[]})
p=图(绘图宽度=900)
lines=[p.line(np.arange(10),np.random.random(10))表示范围(3)内的i]
直线=p.line('x','y',直线颜色='red',直线破折号='虚线',源=源)
回调_tap=''
如果(自定义工具提示的类型=='undefined'){
自定义工具提示=document.createElement('div');
自定义工具提示.setAttribute('id','tooltip\u div');
自定义工具提示.style='位置:绝对;左:0px;顶部:0px;z索引:9999;边框:1px纯黑色;填充:10px;背景:白色;字体系列:arial;字体大小:12px'
document.body.prepend(自定义工具提示);
}        
如果(真===Bokeh.drawing){
Bokeh.drawing=错误
}
否则{
如果(!Bokeh.图纸){
src.data={'x':[],'y':[]}
src.change.emit()
}
src.data['x'].push(cb_obj.x)
src.data['y'].push(cb_obj.y)
Bokeh.drawing=true
Bokeh.sx_start=cb_obj.sx
Bokeh.x_启动=cb_obj.x
Bokeh.sy\U start=cb\U obj.sy
Bokeh.y_启动=cb_对象y
}'''
回调_mousemove=''
函数打印(…参数){
for(args中的i){
console.log(args[i])
}
}
如果(Bokeh.图纸){
if(src.data['x'].length>1){
src.data['x'].pop()
src.data['y'].pop()
}
src.data['x'].push(cb_obj.x)
src.data['y'].push(cb_obj.y)
src.change.emit()
tooltip=document.getElementById('tooltip\u div')
tooltip.style.left=cb_obj.sx+30+'px'
tooltip.style.top=cb_obj.sy+10+'px'
tooltip.innerHTML='Distance X:'+数学圆(cb_obj.sx-Bokeh.sx_start)+'px'+'(单位):'+(数学圆(cb_obj.X-Bokeh.X_start)*100)/100)+'units'+
“
”+ “距离Y:”+数学圆(cb_obj.sy-Bokeh.sy_开始)+“px”+“(单位):”+(数学圆(cb_obj.Y-Bokeh.Y_开始)*100)/100)+“单位” }''' p、 js_on_事件('tap',CustomJS(args={'src':source,},code=callback_tap)) p、 js_on_事件('mousemove',CustomJS(args={'src':source,},code=callback_mousemove)) 表演(p)

这真是太棒了!不过工具提示中有一个问题。是否可以禁用该工具?也许通过右键点击?
import numpy as np
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.events import *

source = ColumnDataSource({'x': [], 'y': []})

p = figure(plot_width = 900)
lines = [p.line(np.arange(10), np.random.random(10)) for i in range(3)]
line = p.line('x', 'y', line_color = 'red', line_dash = 'dashed', source = source)

callback_tap = '''

if (typeof custom_tooltip == 'undefined') {
        custom_tooltip = document.createElement('div');
        custom_tooltip.setAttribute('id','tooltip_div');
        custom_tooltip.style = 'position: absolute; left: 0px; top: 0px; z-index: 9999; border:1px solid black; padding: 10px; background: white; font-family: arial; font-size: 12px'
        document.body.prepend(custom_tooltip);  
}        

if (true === Bokeh.drawing) {
    Bokeh.drawing = false
}
else {
    if (!Bokeh.drawing) {
        src.data = {'x':[], 'y':[]}        
        src.change.emit()
    }

    src.data['x'].push(cb_obj.x)
    src.data['y'].push(cb_obj.y)

    Bokeh.drawing = true
    Bokeh.sx_start = cb_obj.sx
    Bokeh.x_start = cb_obj.x
    Bokeh.sy_start = cb_obj.sy
    Bokeh.y_start = cb_obj.y  
}'''

callback_mousemove = '''
function print(...args) {
    for (i in args) {
        console.log(args[i])
    }
}

if (Bokeh.drawing) {  
    if (src.data['x'].length > 1) {
        src.data['x'].pop()
        src.data['y'].pop()   
    }

    src.data['x'].push(cb_obj.x)
    src.data['y'].push(cb_obj.y)
    src.change.emit()

    tooltip = document.getElementById('tooltip_div')
    tooltip.style.left = cb_obj.sx + 30 + 'px'
    tooltip.style.top = cb_obj.sy + 10 + 'px'
    tooltip.innerHTML = 'Distance X: ' + Math.round(cb_obj.sx - Bokeh.sx_start) + ' px' + ' (units): ' + (Math.round((cb_obj.x - Bokeh.x_start) * 100) / 100) + ' units' + 
                        '<br />' +
                        'Distance Y: ' + Math.round(cb_obj.sy - Bokeh.sy_start) + ' px' + ' (units): ' + (Math.round((cb_obj.y - Bokeh.y_start) * 100) / 100) + ' units' 

}'''

p.js_on_event('tap', CustomJS(args = {'src': source, }, code = callback_tap))
p.js_on_event('mousemove', CustomJS(args = {'src': source, }, code = callback_mousemove))

show(p)