こんにちは。
Bokeh のプロットエリアをウィンドウのサイズに合わせる(リサイズにも追従させてぴったりなエリアサイズへ自動的に変更する)実現方法を調べてみました。
- "How to fit bokeh plot size dynamically" (Stack Overflow)
$ ./bokeh_resize.py
writing a file: bokeh_resize.html
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()