Just a useless raindrops animation

Learning how to use Bokehjs I created this animation on ObservableHQ, it demonstrates:

  • how to load bokehjs on ObservableHQ (not hard, but not straightforward)
  • how to use Bokehjs (including widgets and callbacks)
  • how to create animations

Looks so cool!

1 Like

This is really great! I don’t think I’ve seen anyone try to use Bokeh on Observable before, so it’s great to know it works! If you have any feedback about how to make anything simpler or easier please let us know. Do you mind if we tweet this out from the Bokeh twitter account?


Sure, I’d be happy to see more people using them, as they are both great products and naturally fit together, as python version of Bokeh fits to jupyter notebooks.

In fact, I’ve seen a few posts here (1, 2) and some notebooks on Observable (1, 2) mentioning this integration before, but some of them might be a bit outdated, as they load bokeh.css or manually creating Bokeh.Document which is no longer needed with newer versions. Also I’ve not seen using widgets and animation there. Observable has its own input controls (sliders, checkboxes, buttons), but they seem to be pretty basic and do not look so well (for my taste). They are in active development, so this could be improved in the future.

As for feedback, I think there are a few things to mention:

  1. You can indeed load Bokeh quite easily with a few lines like this:
viewof Bokeh = {
  const v = "2.4.2";
  await require(`https://cdn.bokeh.org/bokeh/release/bokeh-${v}.js`).catch(() => {})
  await require(`https://cdn.bokeh.org/bokeh/release/bokeh-api-${v}.js`).catch(() => {}); 
  await require(`https://cdn.bokeh.org/bokeh/release/bokeh-widgets-${v}.js`).catch(() => {}); 
  const message = md`Bokeh version **${window.Bokeh.version}** loaded`
  message.value = window.Bokeh;
  return message;

Although, it is a bit different than you would do in a regular html page, but this technique is quite common on Observable to load/require libraries that do not export objects, but assign variables on window.

In fact Observable supports (and encourages) a newer mechanism for loading packages via import. If a package is compiled as a ES module, it could be loaded from url:

import Bokeh, { show, figure, HoverTool } from 'https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.esm.min.js';

or by name, if it is available on npm:

import Bokeh, { show, figure, HoverTool } from '@bokeh/bokehjs'

I’m not sure about exact syntax, but there was discussion about it.

I know you are continously working on improving modularization and packaging, but for now if you try to import https://cdn.bokeh.org/bokeh/release/bokeh-api-2.4.2.esm.min.js you’ll get an error as it references non existing file in the first line:

import main from "./bokeh.esm.js";
  1. Another thing that could be better is if there existed a simple way to attach callbacks in Bokehjs for user clicks/property changes. I think this is mentioned in this issue

  2. Also I was missing documentation on how to dispose a bokeh plot. If you rerun multiple times one cell in Observable notebook, there will be created a few plots. While DOM element will be destroyed, I believe there still might remain some references somewhere that need to be disposed. This also relevant for single page applications, where page is not refreshed, when user navigates between different routes.

That’s what I could remember at the moment. Except this everything worked pretty smoothly and I didn’t face major issues.

I think Observable might be a good way to promote Bokehjs as there are many users who are passionate about data exploration, visualization and interactivity, which is Bokeh all about, and these results could be easily shared.