Some (new ?) thoughts about WGLMakie in Pluto

Hi everyone!

I recently used WGLMakie animations in a Pluto notebook for my Habilitation defense. I thought it was really cool so I want to highlight this possibility by making a Pluto “featured notebook”. Here is a comment and a question.

Comment

I started with the instructions given by this discourse topic. However, it turns out that Bonito is not needed (at least in all cases I checked). In fact, you just have to encapsulate your code snippet into a begin ... end block (or a let ... end block if you want local scope variables so that you can reuse the fig variable name across several animations).

Question

Across multiple tests, it seems that each time you run/restart a notebook, the first animation is bugged, i.e. the components (slider, toggle, etc.) are not interactive. But it works very well for the following ones. See the following video for an example.

Do you have any idea about this behavior ?

For completeness, the two code blocks I used come from Makie IntervalSlider and Makie Toggle tutorials. Here they are:

let
	fig = Figure()
	
	ax = Axis(fig[1, 1], limits = (0, 600, -2, 2))
	hidexdecorations!(ax)
	
	t = Observable(0.0)
	points = lift(t) do t
	    x = range(t-1, t+1, length = 500)
	    @. sin(x) * sin(2x) * sin(4x) * sin(23x)
	end
	
	lines!(ax, points, color = (1:500) .^ 2, linewidth = 2, colormap = [(:blue, 0.0), :blue])
	
	gl = GridLayout(fig[2, 1], tellwidth = false)
	Label(gl[1, 1], "Live Update")
	toggle = Toggle(gl[1, 2], active = false)
	
	on(fig.scene.events.tick) do tick
	    toggle.active[] || return
	    t[] += tick.delta_time
	end

	fig
end
let
	f = Figure()
	Axis(f[1, 1], limits = (0, 1, 0, 1))
	
	rs_h = IntervalSlider(f[2, 1], range = LinRange(0, 1, 1000),
	    startvalues = (0.2, 0.8))
	rs_v = IntervalSlider(f[1, 2], range = LinRange(0, 1, 1000),
	    startvalues = (0.4, 0.9), horizontal = false)
	
	labeltext1 = lift(rs_h.interval) do int
	    string(round.(int, digits = 2))
	end
	Label(f[3, 1], labeltext1, tellwidth = false)
	labeltext2 = lift(rs_v.interval) do int
	    string(round.(int, digits = 2))
	end
	Label(f[1, 3], labeltext2,
	    tellheight = false, rotation = pi/2)
	
	points = rand(Point2f, 300)
	
	# color points differently if they are within the two intervals
	colors = lift(rs_h.interval, rs_v.interval) do h_int, v_int
	    map(points) do p
	        (h_int[1] < p[1] < h_int[2]) && (v_int[1] < p[2] < v_int[2])
	    end
	end
	
	scatter!(points, color = colors, colormap = [:gray90, :dodgerblue], strokewidth = 0)
	
	f
end