LoginSignup
0
0

More than 5 years have passed since last update.

Bokehのプロットエリアをウィンドウのサイズに合わせる

Last updated at Posted at 2018-09-28

こんにちは。
Bokeh のプロットエリアをウィンドウのサイズに合わせる(リサイズにも追従させてぴったりなエリアサイズへ自動的に変更する)実現方法を調べてみました。

$ ./bokeh_resize.py 
writing a file: bokeh_resize.html

bokeh_resize.jpg

bokeh_resize.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ref: "How to fit bokeh plot size dynamically" (https://stackoverflow.com/questions/48879674/how-to-fit-bokeh-plot-size-dynamically)

def main():
    import io, sys, random
    aspectRatio = 1
    ndata = 10 * 1000
    filename = 'bokeh_resize.html'
    datax = [random.random()*200 for r in range(ndata)]
    datay = [random.random()*100 for r in range(ndata)]
    color = ["#%02x%02x%02x" % (random.randrange(128, 256), random.randrange(128, 192), random.randrange(128, 192)) for i in range(ndata)]
    html = plotData(datax, datay, color, aspectRatio)
    print(f'writing a file: {filename}', file=sys.stderr)
    with io.open(filename, mode='w', encoding='utf-8') as f:
        f.write(html)
    return

def plotData(datax, datay, color, aspectRatio=None):
    from jinja2 import Template
    from bokeh.embed import components
    from bokeh.plotting import figure
    from bokeh.resources import INLINE
    from bokeh.util.browser import view
    from bokeh.models import WheelZoomTool

    SCATTER_OPTIONS = dict(size=3, marker="circle", alpha=0.8, fill_color=color, line_color=None)
    PLOT_SIZE_OPTIONS = dict(plot_width=1200, plot_height=400)
    PLOT_OPTIONS = dict(sizing_mode='scale_width', tools="pan,wheel_zoom,reset", id="plt_fig", output_backend="webgl")
    ASPECT_OPTIONS = {} if aspectRatio is None else dict(match_aspect=True, aspect_scale=aspectRatio)
    plt = figure(**PLOT_OPTIONS, **ASPECT_OPTIONS, **PLOT_SIZE_OPTIONS)
    plt.scatter(datax, datay, **SCATTER_OPTIONS)
    plt.toolbar.active_scroll = plt.select_one(WheelZoomTool)

    # Define our html template for out plots
    template = Template('''<!DOCTYPE html>
    <head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.4/TweenMax.min.js"></script>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    {{ js_resources }}
    {{ css_resources }}
    </head>
    <body>
    <div id="panel">   
        <div class="col-md-6" id="card1">
            <div class="card">            
                    <div class="row">
                        <div class="col-sm-12">resizable plot area to fit the width of a window</div>
                    </div>        
                    <div id="div1">
                    {{ div1 }}
                    </div>
            </div>
        </div>
    </div>
    <script>
    (function($){
       var po = $('#panel').offset();
       var co = $('#card1').offset();   
       var x=0, y=po.top-co.top;  
            TweenMax.to($("#card1"), 0.5, {x:x, y:y, className:"col-md-12"});
            TweenMax.to($("#div1"), 0.5, {onComplete:function(){Bokeh.index["plt_fig"].resize();}});
          $(window).resize();
          $(window).trigger('resize');     
    })(jQuery);
    </script>
    </body>
    </html>
    ''')

    resources = INLINE
    js_resources = resources.render_js()
    css_resources = resources.render_css()
    script, div = components(plt)
    div1 = div + script
    html = template.render(js_resources=js_resources,
                           css_resources=css_resources,
                           div1=div1)
    return html

if __name__ == '__main__':
    main()
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0