[WIP] Figures.jl - Draggable interactive figures for plots in a browser

Hello :wave:

This is a little package I threw together a while ago and have kicked it around enough that it might be worth sharing.

It is still a work-in-progress, but I’d love to get some feedback / suggestions if anyone is interested.

The idea is to use a blank browser page as something like a desktop to hold interactive draggable plotting windows.

For instance, you can startup a local server by runing

julia> using Figures; Figures.examples()

and open a browser to http://localhost:8000/examples/blank, where you will be greeted by a completely blank web page. Woo hoo! :tada::blush:

Then from the REPL, you can run

julia> figure(1)

and a draggable figure appears.

To avoid conflicts with plotly.js, the draggable zone, i.e. the area you need to click to drag the window, is a small strip along the top of the figure window. Double clicking the top strip deletes the figure.

The first version of Figures.jl used PlotlyJS.jl, but I decided to just write my own plotly.js API instead and avoid the dependency (e.g. PlotlyJS.jl depends on Blink.jl).

import Figures: Scatter, Layout, Config, Title # I should probably export these 😅
function example_plotly(id,n=10)
    data = [Scatter(;x=1:n,y=rand(n))]
    layout = Layout(;
        title = Title(text="Create a new figure and plot a single trace"),
        width = 650,
        height = 450
    )
    config = Config(displayModeBar=false)
    Plotly.newPlot(id,data,layout=layout,config=config)
end

then

julia> example_plotly("Plot1",50)

gives

If you run the function again with the same name (i.e. div id), it will put the chart in the same figure.If you give it a new name, it will create a new figure, e.g.

julia> example_plotly("Plot2",50)

As mentioned, the figures can be dragged around and placed wherever forming a kind of dashboard.

I like plotly.js because it is web based and interactive. Figures.jl preserves all of the plotly.js interactivity, e.g. data tips upon hovering the mouse over data

zooming in on a region

etc.

There is a more detailed example if you open the browser to http://localhost:8000/examples/plot.ly, you’ll see two buttons:

Clicking “Generate Plots” will send a message to Julia via callback to generate 4 plots overlaid on top of each other that can be arranged however you like:

There is a little fancy trick here. If you open a second tab and view the windows side by side, the “Broadcast Plots” will send the plots to all open windows, i.e. one window is control the display of another window.

Aside from the new Plotly API (which was more work than I’d like to admit), this is all pretty simple stuff. No rocket science here, but I expect it to be useful for my research and hope maybe someone else finds it interesting as well :blush:

6 Likes

Nice work! From the example code, I see that you use your Pages.jl package to implement the button that trigger Julia code. Is there a plan to provide some other widgets (as part of Figures) to send data back to Julia, such as sliders, or mouse-position when clicking in the charts? Not sure if that is even feasible within Plotly charts…

Hi @leethargo :wave:

Thanks :blush:

Is there a plan to provide some other widgets (as part of Figures) to send data back to Julia, such as sliders, or mouse-position when clicking in the charts? Not sure if that is even feasible within Plotly charts…

Another thing I like about plotly.js is that it is built on top of d3.js so yes, it is absolutely feasible to add widgets, mouse positions etc. It is just a matter of priorities. If there was something in particular, I could prioritize that :blush:

You better prioritize according to your own needs :wink:

I’m currently playing with Makie for interactive visualizations of a graph, where I want to, e.g. highlight edges of a node when clicking near that node, but also allow editing of the graph structure. I think that this will work out well, but it would be even better to have something that works in the browser.

That sounds cool :+1:

Oh yes. My dream is to allow Makie to work with browsers :heart_eyes: This is a babystep in that direction :slight_smile: