散景:如何单击并拖动以显示点之间的位移 [英] Bokeh: How to click and drag to display displacement between points

查看:61
本文介绍了散景:如何单击并拖动以显示点之间的位移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够在图形上的两点之间单击并拖动,并显示两点之间的位置变化,并显示一条连接两点的线.我该如何解决这个问题?

I want to be able to click and drag between two points on my graph and display the change in position between points and display a line connecting the two points. How can I go about approaching this?

推荐答案

您可以使用这样的JS回调(Bokeh v1.3.0)来实现它:

You can realize it with JS callback like this (Bokeh v1.3.0):

import numpy as np
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS, Div, Row
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)]
lilne = p.line('x', 'y', line_color = 'red', line_dash = 'dashed', source = source)
div = Div(text='')

callback_tap = '''
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
}'''

callback_mousemove = '''
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()

    div.text = 'Distance: ' + Math.round(cb_obj.sx - Bokeh.sx_start) + ' px' + ' (' + (Math.round((cb_obj.x - Bokeh.x_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, 'div': div}, code = callback_mousemove))

show(Row(p, div))

在图上的第一次单击将开始该行,再单击一次将结束该行.

The first click on the plot starts the line, the next click ends it.

或者,如果您希望使用类似工具提示的div外观,则可以使用以下更复杂的代码来动态添加工具提示div:

Or if you prefer a tooltip-like div appearance you could use this a little bit more complicated code which dynamically adds a tooltip 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)

这篇关于散景:如何单击并拖动以显示点之间的位移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆