1

For my app, I need the user to click an area on a plot, then the plot responds to that click and shows a new plot that is linked to that input click.

However, currently it runs, but the new plot only displays for 3 seconds and then goes back to the original plot. I found a similar example here. This plot updates based on a list of reactiveValues then draws those new points the user selected. I think if I find a way to modify it to draw the new plot immediatly after the clicked event it should work, but stuck on this part.

So ideally the below example will add the new point immediatly after beind clicked. In my case I will need to display the new plot until a new area of the plot is clicked.

Example from the link

library(shiny)

ui <- basicPage(
  plotOutput("plot1", click = "plot_click"),
  verbatimTextOutput("info"),
  actionButton("updateplot", "Update Plot:")
)

server <- function(input, output) {
  val <- reactiveValues(clickx = NULL, clicky = NULL)

  observe({
    input$plot_click
    isolate({
      val$clickx = c(val$clickx, input$plot_click$x)
      val$clicky = c(val$clicky, input$plot_click$y)     
    })
  }) #adding clicks to list

  output$plot1 <- renderPlot({
    plot(mtcars$wt, mtcars$mpg)
    input$updateplot
    isolate({
      points(val$clickx, val$clicky)
    })
  })

  output$info <- renderText({
    paste0("x = ", val$clickx, ", y = ",val$clicky, "\n")
  })

}

shinyApp(ui, server)

2 Answers 2

4

This example shows a main plot and upon click in the main plot it shows a sub plot. Once clicked again it shows again the main plot.

The idea is that a counter (trigger) is increased whenever a click happens. It is important to use req(.) in the observer, lest the observer fires again when the mouse button is released (in this case input$plot_click is set to NULL).

The renderPlot(.) then takes a dependency on this trigger and shows either the main or the sub plot.

Update. If you want to use info from the input$plot_click object you should save it as well, to avoid that it get NULL.

library(shiny)
library(ggplot2)

ui <- basicPage(
   plotOutput("plot1", click = "plot_click")
)

server <- function(input, output) {
   plot_data <- reactiveValues(trigger = 0, x = NA, y = NA)

   observe({
      req(input$plot_click)
      isolate(plot_data$trigger <- plot_data$trigger + 1)
      plot_data$x <- input$plot_click$x
      plot_data$y <- input$plot_click$y
    })

   output$plot1 <- renderPlot({
      if (plot_data$trigger %% 2 == 0) {
         plot(1:10, main = "Main Plot")
      } else {
         ggplot() + geom_point(aes(x = plot_data$x, y = plot_data$y), size = 5, shape = 19)
      }
   })
}

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

4 Comments

This is exactly what I am looking for, but just need to adjust it for where the user clicks. I tried to adjust your code and replace the else statement you provided with ggplot()+geom_point(aes(x=input$plot_click$x,y=input$plot_click$y),size=5,shape=19) but then upon clicking the graph, I get the following error: All columns in a tibble must be 1d or 2d objects: * Column x is NULL, * Column y is NULL
When I call it in my actual program, it shows the new plot for a second, then an argument of length zero error.
See my updated response. Basically you should store the values of the click event, becasue otherwise they will get overwritten by NULL the moment you release the mouse.
Brilliant. Anyway to avoid the double click? I thought maybe take out the trigger but then the original plot I need doesn't appear.
2

Just drop the isolate in your renderPlot:

library(shiny)

ui <- basicPage(
  plotOutput("plot1", click = "plot_click"),
  verbatimTextOutput("info")
)

server <- function(input, output) {
  val <- reactiveValues(clickx = NULL, clicky = NULL)

  observe({
    input$plot_click
    isolate({
      val$clickx = c(val$clickx, input$plot_click$x)
      val$clicky = c(val$clicky, input$plot_click$y)     
    })
  }) #adding clicks to list

  output$plot1 <- renderPlot({
    plot(mtcars$wt, mtcars$mpg)
    points(val$clickx, val$clicky)
  })

  output$info <- renderText({
    paste0("x = ", val$clickx, ", y = ",val$clicky, "\n")
  })

}

shinyApp(ui, server)

Comments

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.