简体   繁体   中英

R Shiny: relayout plotly annotations

I want a plotly plot to change an annotation if the user clicks a button in a shiny app. I have no idea why this does not work:

library(shiny)
library(plotly)

d <- data.frame(x = c(1,2,3), y = c(9,99,999))


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

actionButton("button", "toggle visibility"))

server <- function(input, output) {

output$plot <- renderPlotly({

plot_ly(d)%>%
  add_lines(y=d$y, x= d$x)%>%
  layout(annotations = list(x = 2, y= 99 , text = "hi"))})

  observeEvent(input$button, {
    plotlyProxy("plot", session= shiny::getDefaultReactiveDomain()) %>%
      plotlyProxyInvoke("relayout", list(annotations= list(x = 2, y= 99 , 
text = "ho")))})}

shinyApp(ui, server)

That is not the way to use relayout in plotly . See below for your example using relayout .

I prefer using native shiny buttons for this purpose because of the greater flexibility it offers. Here is how one might go about achieving the hi-ho toggle.

shiny way

library(shiny)
library(plotly)

d <- data.frame(x = c(1,2,3), y = c(9,99,999))


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

  actionButton("button", "toggle visibility"))

server <- function(input, output) {

  output$plot <- renderPlotly({
    p <- plot_ly(d)%>%
      add_lines(y=d$y, x= d$x)
    if (is.null(input$button) | (input$button%%2 == 0)) {
      p <- p %>% layout(annotations = list(x = 2, y= 99 , text = "hi"))
    } else {
      p <- p %>% layout(annotations = list(x = 2, y= 99 , text = "ho"))
    }
    p
  })
}

shinyApp(ui, server)

In this case though, it is simple enough to make the relayout feature work, although it does require an extra button.

plotly relayout way

library(shiny)
library(plotly)

d <- data.frame(x = c(1,2,3), y = c(9,99,999))


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

server <- function(input, output) {
  output$plot <- renderPlotly({
    updatemenus <- list(
      list(
        active = -1,
        type = 'buttons',
        buttons = list(
          list(
            label = "hi",
            method = "relayout",
            args = list(list(annotations = list(list(x = 2, y= 99 , text = "hi"))))), 
          list(
            label = "ho",
            method = "relayout",
            args = list(list(annotations = list(list(x = 2, y= 99 , text = "ho")))))
          )
      )
    )
    p <- plot_ly(d) %>%
      add_lines(y=d$y, x= d$x) %>% 
      layout(updatemenus = updatemenus)
    p
  })
}

shinyApp(ui, server)

I believe all that needs to change in your code in order to get this to work is wrapping another list around the defined annotation list in your plotly proxy relayout code. I recently discovered that this recursive list structure is all that's needed in order to manipulate annotations using relayout - you can check out my answer to another SO question related to the same issue, but with slightly different context: https://stackoverflow.com/a/70610374/17852464

    library(shiny)
    library(plotly)
    
    d <- data.frame(x = c(1,2,3), y = c(9,99,999))
    
    ui <- fluidPage(
      plotlyOutput("plot"),
      
      actionButton("button", "toggle visibility"))
    
    server <- function(input, output) {
    
      output$plot <- renderPlotly({
        plot_ly(d)%>%
          add_lines(y=d$y, x= d$x)%>%
          layout(annotations = list(x = 2, y= 99 , text = "hi"))
        })
      
      observeEvent(input$button, {
        plotlyProxy("plot", session= shiny::getDefaultReactiveDomain()) %>%
          plotlyProxyInvoke("relayout", list(annotations= list(list(x = 2, y= 99 , 
                                                               text = "ho"))))})}
      
    }
    
    shinyApp(ui, server)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM