I attempt to capture plotly_legenddoubleclick
events to trigger a styling event in a second plot. When the user double clicks a legend group, the group is highlighted in the corresponding scatterplot using an opacity 'hack'. In practice, this works for the first series of double-clicks but becomes out of sync and eventually stops working.
MWE and GIF of behaviour below.
library(shiny)
library(plotly)
data = iris
ui <- fluidPage(
mainPanel(
plotlyOutput("bp"),
plotlyOutput("sc")
)
)
server <- function(input, output) {
serv_data <- reactive({ df <- data })
output$bp <- renderPlotly({
fig <- plot_ly(
data,
source = "boxplot",
y = ~Sepal.Length,
color = ~Species,
type = "box"
) %>%
event_register("plotly_legenddoubleclick")
})
output$sc <- renderPlotly({
if(!is.null(legend_data$data)) {
df <- legend_data$data
}else{
df <- data
df$opacity <- 0.75
}
fig <- plot_ly(
df,
source = "scatter",
x = ~Sepal.Width,
y = ~Sepal.Length,
type = "scatter",
mode = "markers",
color = ~Species,
opacity = ~opacity
)
})
## Double click stuff
legend_data <- reactiveValues(data = NULL)
observeEvent(event_data("plotly_legenddoubleclick", source = "boxplot"), {
clicked_data <- event_data("plotly_legenddoubleclick", source = "boxplot")
if (is.null(legend_data$data)) {
clicked_species <- clicked_data$name
mat <- serv_data()
mat <- mat %>% mutate(opacity = ifelse(Species == clicked_species, 1.0, 0.2))
legend_data$data <- mat
} else {
legend_data$data <- NULL
}
})
}
shinyApp(ui = ui, server = server)
The wrong display occurs when the second time a group is "un-selected", e.g. in your GIF after the second double-click on versicolor
. This is because you have an observeEvent
on event_data("plotly_legenddoubleclick", source = "boxplot")
and this isn't triggered because in event_data
the "resetting" of the plot already has a storage and event_data
acts in a lazy-sense (see below).
What you need to do is to always trigger the re-execution. From ?event_data
:
Arguments
...
priority: the priority of the corresponding shiny input value. If equal to "event", then event_data() always triggers re-execution, instead of re-executing only when the relevant shiny input value changes (the default).
You need priority = "event"
(instead of the default "input"
), hence you can change the condition in the observeEvent
to the following and it will work:
observeEvent(event_data(
"plotly_legenddoubleclick",
source = "boxplot",
priority = "event"
), {
# your Code as above
}