Interactivity and Pluto

Today we’ll finally see the power of Pluto. Not only does it make it easy to iterate on your code, but it goes beyond that, and natively supports interacting with your code through JavaScript and HTML.

Overview

Here, we have yet again a feature that wasn’t built via retrofitting, rather via utilising the foundational principles of both Julia and Pluto. This shouldn’t be thought of as a suite, but instead as clever gluing of parts. Julia’s homoiconicity provides a way of easily automating writing code that then writes the code which actually implements concrete stuff. Pluto facilitates the reactive interaction between visual interfaces and compiled code. Don’t worry if this sounds complex, its not, and we’ll see that presently.

PlutoUI

We start by talking about PlutoUI.jl a package that, as the name suggests, eases making UI in Pluto. First step of course is to add it to your project:

(@v1.5) pkg> add PlutoUI
   Updating registry at `~/.julia/registries/General`
######################################################################## 100.0%
  Resolving package versions...
  Installed Suppressor ─ v0.2.0
  Installed FFTW_jll ─── v3.3.9+7
  Installed PlutoUI ──── v0.6.10
Downloading artifact: FFTW
Updating `~/.julia/environments/v1.5/Project.toml`
  [7f904dfe] + PlutoUI v0.6.10
Updating `~/.julia/environments/v1.5/Manifest.toml`
  [f5851436] ↑ FFTW_jll v3.3.9+6 ⇒ v3.3.9+7
  [7f904dfe] + PlutoUI v0.6.10
  [fd094767] + Suppressor v0.2.0

Now, to start, let’s look at some HTML

begin
	r= @bind range html"<input type=range min=5 max=15>"
	p= @bind power Slider(-2:5)
	
	md"""
	$(r) $(p)
	
	power= $(range)
	range= $(power)
	"""
end

This gives you a slider as expected. But you can simplify life by using PlutoUI. This is how it looks in action:

A neat example

Following is the code I’ve copied from a sample notebook that comes along with Pluto:

@bind dims html"""
<canvas width="200" height="200" style="position: relative"></canvas>

<script>
// 🐸 `currentScript` is the current script tag - we use it to select elements 🐸 //
const canvas = currentScript.closest('pluto-output').querySelector("canvas")
const ctx = canvas.getContext("2d")

var startX = 80
var startY = 40

function onmove(e){
	// 🐸 We send the value back to Julia 🐸 //
	canvas.value = [e.layerX - startX, e.layerY - startY]
	canvas.dispatchEvent(new CustomEvent("input"))

	ctx.fillStyle = '#ffecec'
	ctx.fillRect(0, 0, 200, 200)
	ctx.fillStyle = '#3f3d6d'
	ctx.fillRect(startX, startY, ...canvas.value)
}

canvas.onmousedown = e => {
	startX = e.layerX
	startY = e.layerY
	canvas.onmousemove = onmove
}

canvas.onmouseup = e => {
	canvas.onmousemove = null
}

// Fire a fake mousemoveevent to show something
onmove({layerX: 130, layerY: 160})

</script>
"""

And here is how it looks:

Further notes

You could very well set up a PaaS to have a notebook on your website itself, but that’s a tale for another time. You can find the complete notebook at the following link:

https://github.com/mathmetal/Misc/blob/master/MLG/PlutoUI.jl

Also, know that you can fully lean on your knowledge of JavaScript and make things happen in Pluto. Alas, my knowledge of that framework is limited, but I hope it helps you to understand the basics.

References

  1. https://juliahub.com/docs/PlutoUI/abXFp/0.6.3/autodocs/
  2. https://github.com/fonsp/Pluto.jl/blob/master/sample/Interactivity.jl

Leave a Reply

Your email address will not be published.