Hi there! Mostly a question for @sdanisch I guess, but maybe others know as well…
I’m creating interactive plots that work offline using WGLMakie and JSServe. For this, I have a custom function that takes a function with a single paramter (an Observable) and returns a Figure
:
"""
Produce an interactive figure with a slider.
Paramters:
fig_fun: Function that takes a single argument, the Observable that the slider is controlling, and returns a Figure.
val_range: Range of values that the slider can take.
path: Path to save the figure to.
pt_per_unit: Number of points per unit for plotting.
"""
function produce_interactive_figure_with_slider(fig_fun::Function, val_range::Union{AbstractVector, AbstractRange}, path::String; pt_per_unit = 1)
# we neet the webgl backend for this
WGLMakie.activate!()
app = App() do session::Session
_slider_range = 1:length(val_range)
_slider = JSServe.Slider(_slider_range)
# map slider values to actual values (should work without doing this, but seems a bit buggy)
_value = map(_slider) do idx
return val_range[idx]
end
# create the slider div
slider_div = DOM.div(_slider)
# get figure
fig = fig_fun(_value)
# the figure div
fig_div = DOM.div(fig)
# add same styles for consistent dimensions
width, height = size(fig.scene);
s = Hyperscript.HTML("<style> canvas {width:$(pt_per_unit*width) pt !important; height:auto !important;} </style>")
# record state map
return JSServe.record_states(session, DOM.div(s, fig_div, slider_div))
end
# save to disk
open(path, "w") do io
show(io, MIME"text/html"(), Page(exportable=true, offline=true))
show(io, MIME"text/html"(), app)
end
# TODO: output as widget for jupyter
end
This generally works really well. However, I have a number of “legacy” figures and also some figures that don’t play well with using Observable (like figures using AlgebraOfGraphics), so I would like to be able to do something like this:
fig_fun = x -> @lift my_figure($x)
produce_interactive_figure_with_slider(fig_fun, ...)
I tried passing an Observable to DOM.div(fig)
, which works but results in only the first state being shown and the plot disappearing after moving the slider.
Super thankful for any suggestions!