Plots and click events

Hi All,
I wonder, if any of the Plots’ backends provides an infrastructure to handle click events. According to this page Click events in Julia, PlotlyJS should support it. However, I’d be keen to use the plotlyjs() backend if possible.

I’d appreciate any suggestions.

This animation example shows how to query the position of the pointer as well as the state of the buttons in GR.

2 Likes

Nice! Thank you!

So, GR offers the samplelocator() function which returns current x, y coordinates and the clicked mouse button.
Here is a MWE:

using GR
plot(rand(10,2))
x, y, button = samplelocator() 
while button == 0 
  @show x,y,button = samplelocator() 
  sleep(.01) 
end

The output would be something like this:

(x, y, button) = samplelocator() = (0.9119601328903655, 0.2168141592920354, 0)
(x, y, button) = samplelocator() = (0.8903654485049833, 0.25442477876106195, 0)
(x, y, button) = samplelocator() = (0.8754152823920266, 0.2743362831858407, 0)
(x, y, button) = samplelocator() = (0.8504983388704319, 0.3075221238938053, 0)
(x, y, button) = samplelocator() = (0.8239202657807309, 0.331858407079646, 0)
(x, y, button) = samplelocator() = (0.813953488372093, 0.3407079646017699, 0)
(x, y, button) = samplelocator() = (0.7940199335548173, 0.3517699115044248, 0)
(x, y, button) = samplelocator() = (0.7558139534883721, 0.36283185840707965, 0)
(x, y, button) = samplelocator() = (0.739202657807309, 0.36283185840707965, 0)
(x, y, button) = samplelocator() = (0.7325581395348837, 0.36283185840707965, 0)
(x, y, button) = samplelocator() = (0.7325581395348837, 0.36283185840707965, 0)
(x, y, button) = samplelocator() = (0.707641196013289, 0.3561946902654868, 0)

This is a nice to have raw functionality, but it still falls short of being a proper mouse/click events handler. E.g., it would be hard to capture a click on a data point in the plot using samplelocator().

I wonder if there are some other solutions.

Such functionalities (selection mechanisms, “editing” of plots) are provided in the GRM library, which is still WIP.

At this stage, this requirement could only be implemented with QML (there are several demos in the examples directory) - but the selection of points would be done at the application level, which is probably not what you want.

In a future version, your requirement will be solved much more elegantly with GRM.

1 Like

Thanks! Looking forward to the update!

Here is an adaptation of that PlotlyJS example (Click events in Julia) but using just the Plots.jl interface calls. I’m assuming the plotlyjs backend for Plots.jl is set up. Hope it helps.

import Plots
import Plots: KW
Plots.plotlyjs()

color_vec = [fill("blue",10),  fill("red",10)]

pl = Plots.scatter(
    1:10,
    rand(10),
    extra_kwargs = KW(
        :series => KW(
                      :showlegend => true,
                      :mode => "lines+markers+text",
                      :name => "blue-green",
                      :marker => KW(:color => color_vec[1], :symbol => "circle", :size => 10),
                      :line => KW(:dash => "dash", :width => 2),
                      ),
    )
)

Plots.scatter!(pl,
   1:10,
   rand(10),
   extra_kwargs = KW(
       :series => KW(
                     :name => "red-purple",
                     :mode => "lines+markers+text",
                     :marker => KW(:color => color_vec[2], :symbol => "circle", :size => 10)                
                     ),
    )
)

display(pl)

p = Plots.backend_object(pl)

using Plots.PlotlyJS.WebIO

on(p["click"]) do data
    color_vec_alt = [fill("green",10),  fill("purple",10)]
    symbols = [fill("circle", 10), fill("circle", 10)]
    for point in data["points"]
        color_vec_alt[point["curveNumber"] + 1][point["pointIndex"] + 1] = "gold"
        symbols[point["curveNumber"] + 1][point["pointIndex"] + 1] = "star"
    end
    Plots.PlotlyJS.restyle!(p, marker_color=color_vec_alt, marker_symbol=symbols)
end
1 Like

Great! That works indeed. Thanks for the adaptation of that example!
The Plots.backend_object() turns out to be the missing link.

There is a grain of salt though. The trick doesn’t work in Pluto (my initial intention): Plots.backend_object(pl) returns Nothing.

Base on WebIO & PlotlyJS support? · Issue #299 · fonsp/Pluto.jl · GitHub, my understanding is that native PlotlyJS is not yet supported by Pluto. So, it seems there is no way to hook into those js events in a Pluto notebook at the moment, isn’t it?

Have a look at GitHub - JuliaPluto/PlutoPlotly.jl for using Plotly within Pluto. It also has an example for event listening.

1 Like

Fantastic! Exactly what I was looking for. Thanks a lot for the link!