Search code examples
rshinyplotly

Click and zoom in a plot_ly in R Shiny application without reinitialisation


I am using R Shiny and I am plotting some 3D point cloud with plot_ly from the library plotly. I can move and zoom on the points.

When I click on some point, some information about the point is stored in a variable, but then this resets the visualization.

It is possible to prevent this reinitialization? E.g. I would like to zoom on some part of the data, and then successively click on the points without any reset..

Here is a reproducible example :

library(shiny)
library(plotly)

df=iris

ui <- fluidPage(
  plotlyOutput("plot3D"),
  textOutput("selection")
)

server <- function(input, output, session) {
  
  react <- reactiveValues(value = 0)
  
  output$plot3D <- renderPlotly({
    
    click_data <- event_data("plotly_click", priority   = "event")

    if (!is.null(click_data)) {
      react$value<-click_data$customdata
    }
    
    fig<-plot_ly(df,
                 x=~Sepal.Length,y=~Sepal.Width,z=~Petal.Length,
                 type="scatter3d",
                 mode = 'markers',
                 customdata = ~Species
    )
    fig
  })
  
  output$selection <- renderPrint({
    react$value
  })

}

shinyApp(ui = ui, server = server)

And here is a gif about what happens :

R shiny plot with click


Solution

  • The issue is, that you are collecting the event_data inside your renderPlotly call. Accordingly your plot is re-rendered with each click event (reactive dependency).

    Please check the following:

    library(shiny)
    library(plotly)
    library(datasets)
    
    DF <- iris
    
    ui <- fluidPage(plotlyOutput("plot3D"),
                    textOutput("selection"))
    
    server <- function(input, output, session) {
      output$plot3D <- renderPlotly({
        plot_ly(
          DF,
          x =  ~ Sepal.Length,
          y =  ~ Sepal.Width,
          z =  ~ Petal.Length,
          type = "scatter3d",
          mode = 'markers',
          customdata = ~ Species,
          source = "myscatter3d"
        )
      })
      
      click_data <- reactive({
        event_data("plotly_click", source = "myscatter3d", priority = "event")
      })
      
      output$selection <- renderPrint({
        click_data()
      })
      
    }
    
    shinyApp(ui = ui, server = server)