Search code examples
bokeh

Changing cursor on a bokeh map


I've made a map using Bokeh, like the first example on this page, except the user can zoom in/out by scrolling up/down, and can tap circles I've added to the map to select them.

At the moment when the cursor is over the map it's the default arrow. If I click and drag the map the cursor changes to the text cursor for some reason. It doesn't change with any other action.

I'd like to be able to change the cursor appearance so that:

  1. When over the map it's the grab cursor
  2. When dragging the map it's the grabbing cursor
  3. When over a circle it's the pointer cursor

I can achieve (1) with:

.bk { cursor: grab; }

but I'm not sure how to achieve the other two.


Solution

  • Following suggestions from the other post I came with this: (works for Bokeh v1.3.0):

    from bokeh.models import CustomJS, HoverTool
    from bokeh.plotting import figure, show
    
    p = figure(tools='pan, tap, reset')
    p.circle(x=[1,2,3], y=[1,2,3], size=30)
    
    code_pan_start = '''
        Bokeh.grabbing = true
        var elm = document.getElementsByClassName('bk-canvas-events')[0]
        elm.style.cursor = 'grabbing'  
    '''
    
    code_pan_end = '''
        if(Bokeh.grabbing) {
            Bokeh.grabbing = false
            var elm = document.getElementsByClassName('bk-canvas-events')[0]
            elm.style.cursor = 'grab'        
        }
    '''
    
    code_hover = '''
    if((Bokeh.grabbing == 'undefined') || !Bokeh.grabbing) {
        var elm = document.getElementsByClassName('bk-canvas-events')[0]
        if (cb_data.index.indices.length > 0)
            elm.style.cursor = 'pointer' 
        else
            elm.style.cursor = 'grab'
    }
    '''
    
    p.js_on_event('panstart', CustomJS(code = code_pan_start))
    p.js_on_event('panend', CustomJS(code = code_pan_end))
    
    p.add_tools(HoverTool(callback = CustomJS(code = code_hover)))
    
    show(p)
    

    enter image description here