Skip to content

Instantly share code, notes, and snippets.

@daattali
Last active March 12, 2026 07:51
Show Gist options
  • Select an option

  • Save daattali/9440f0b278dbbf538b3587e026811426 to your computer and use it in GitHub Desktop.

Select an option

Save daattali/9440f0b278dbbf538b3587e026811426 to your computer and use it in GitHub Desktop.
# I'm trying to let the user select points and paint them in a certain colour, and if the user clicks on a point then paint that point a different colour.
# It looks like the pointNumber and curveNumber data that plotly returns are different for the same points. I'm not sure how curveNumber works, but to me it doesn't make sense yet :)
# Any help is appreciated!
library(plotly)
library(shiny)
ui <- fluidPage(
plotlyOutput("plot")
)
server <- function(input, output, session) {
output$plot <- renderPlotly({
click_data <- event_data("plotly_click", source = "select")
select_data <- event_data("plotly_selected", source = "select")
data <- mtcars
data$col <- "black"
if (!is.null(select_data)) {
cat(str(select_data))
idx <- select_data$pointNumber + 1
data[idx, "col"] <- "blue"
}
if (!is.null(click_data)) {
cat(str(click_data))
idx <- click_data$pointNumber + 1
data[idx, "col"] <- "red"
}
p <- ggplot(data, aes(mpg, wt, col = I(col))) + geom_point()
ggplotly(p, source = "select")
})
}
shinyApp(ui, server)
# This is very similar to the previous file, but I tried applying Carson's advise of setting the key aesthetic to row names
library(plotly)
library(shiny)
ui <- fluidPage(
plotlyOutput("plot")
)
server <- function(input, output, session) {
output$plot <- renderPlotly({
click_data <- event_data("plotly_click", source = "select")
select_data <- event_data("plotly_selected", source = "select")
data <- mtcars
key <- row.names(data)
data$col <- "black"
if (!is.null(select_data)) {
cat(str(select_data))
idx <- select_data$pointNumber + 1
data[idx, "col"] <- "blue"
}
if (!is.null(click_data)) {
cat(str(click_data))
idx <- click_data$pointNumber + 1
data[idx, "col"] <- "red"
}
p <- ggplot(data, aes(mpg, wt, col = I(col), key = key)) + geom_point()
ggplotly(p, source = "select")
})
}
shinyApp(ui, server)
@asadow
Copy link

asadow commented Apr 16, 2024

Is it possible to maintain the same zoom state after click/selection?

@ismirsehregal
Copy link

ismirsehregal commented Mar 10, 2026

@asadow a little late but you can maintain the zoom state by using plotlyProxy to modify the plotly object instead of re-rendering it:

library(shiny)
library(plotly)

ui <- fluidPage(
  plotlyOutput("my_plot"),
  verbatimTextOutput("click"),
  verbatimTextOutput("selected")
)

server <- function(input, output, session) {
  
  nms <- row.names(mtcars)
  
  output$my_plot <- renderPlotly({
    p <- plot_ly(
      mtcars,
      x = ~mpg,
      y = ~wt,
      customdata = nms,
      selected = list(marker = list(color = "red")),
      type = "scatter",
      mode = "markers"
    ) |>
      layout(dragmode = "select") |>
      event_register("plotly_selected") |>
      event_register("plotly_click") |>
      event_register("plotly_doubleclick")
  })
  
  output$click <- renderPrint({
    d <- event_data("plotly_click")
    if (is.null(d)) "Click events appear here (double-click to clear)" else d
  })
  
  output$selected <- renderPrint({
    d <- event_data("plotly_selected")
    if (is.null(d)) "Selected points appear here (double-click to clear)" else d
  })
  
  plot_proxy <- plotlyProxy("my_plot", session, deferUntilFlush = TRUE)
  
  plotly_click <- reactive(event_data("plotly_click"))
  plotly_doubleclick <- reactive(event_data(event = "plotly_doubleclick", source="my_plot"))
  plotly_selected <- reactive(event_data(event = "plotly_selected", source="my_plot"))
  
  observeEvent(plotly_click(), {
    # plotlyProxyInvoke(plot_proxy, "restyle", list(selectedpoints = -1)) # deselect all points for all traces
    plotlyProxyInvoke(plot_proxy, "restyle", list(selectedpoints = list(I(plotly_click()$pointNumber))), plotly_click()$curveNumber)
  })
}

shinyApp(ui, server)

Here my related SO answer can be found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment