1

I have a Shiny app with plotly graphs that are modified via plotlyProxy() in response to user input. Right now the graph modification is instantaneous and abrupt, so I'm trying to use plotly's animation frames to code for smooth changes.

For example, some reproducible code:

# reproducible code for stack overflow 
library(plotly)
library(tidyverse)

lvls <- c("lv1", "lv2", "lv3", "lv4")
dat <- data.frame(var1 = sample(lvls, 300, replace = T))

ui <- fluidPage(
  plotlyOutput("plot")

)

server <- function(input, output, session) {

  output$info <- renderPrint(event_data("plotly_click"))

  output$plot <- renderPlotly({
    p <- plot_ly(dat, x = ~var1) %>% 
      add_histogram()
    p
  })

  observeEvent(event_data("plotly_click"),
               {
                 click <- event_data("plotly_click")
                 level <- click$x
                 opacity <- lvls %>% 
                   as_tibble() %>% 
                   mutate(opacity = ifelse(value == level, 1, .15)) %>% 
                   .$opacity

                 plotlyProxy("plot", session) %>% 
                   plotlyProxyInvoke("restyle",
                                     list(marker.opacity = list(opacity)))

               })


}

shinyApp(ui = ui, server = server)

When you run this app and click on each of the bars, the selected bar is highlighted without re-rendering the plot thanks to plotlyProxy(). How can I make the highlighting transition smooth with plotly's animation frames?

1 Answer 1

1

Not sure if this is sufficient, because you were explicitly asking for animations. Nevertheless, here is a solution providing you with the expected behaviour by repeated restyling of the plot:

library(plotly)
library(tidyverse)

lvls <- c("lv1", "lv2", "lv3", "lv4")
dat <- data.frame(var1 = sample(lvls, 300, replace = T))

ui <- fluidPage(
  plotlyOutput("plot")
)

server <- function(input, output, session) {

  output$info <- renderPrint(event_data("plotly_click"))

  output$plot <- renderPlotly({
    p <- plot_ly(dat, x = ~var1) %>% 
      add_histogram()
    p
  })

  observeEvent(event_data("plotly_click"), {
    click <- event_data("plotly_click")
    level <- click$x

    opacityVec <- seq(.1,1,.1)
    revOpacityVec <- rev(opacityVec)

    for(i in seq_along(opacityVec)){
      opacity <- lvls %>% 
        as_tibble() %>% 
        mutate(opacity = ifelse(value == level, opacityVec[i], revOpacityVec[i])) %>% 
        .$opacity

      plotlyProxy("plot", session) %>% 
        plotlyProxyInvoke("restyle",
                          list(marker.opacity = list(opacity)))

      Sys.sleep(0.03)
    }

  })

}

shinyApp(ui = ui, server = server)
Sign up to request clarification or add additional context in comments.

1 Comment

This got me off to a great start. I'll try to code for the case that, when I click on a new bar, the opacity loop isn't reset to 1 for the remaining bars.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.