Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

plotly click events from anywhere on the plot

I am new to r-plotly and trying to figure out how to handle clicks which are not on the data. It seems that using event_data("plotly_click") I get events that are on points from the data, but so far have not figured out how to do this for clicks which are not close to the data, but just on the white part of the plot.

Shiny click events from plots can do this and I just get the x and y of the click. I want similar, but for plotly plots.

Can I specify click events to be from anywhere on the plotly plot, not just on the data?

EDIT: Surprisingly this does not exist yet in plotly. See this feature request

https://github.com/plotly/plotly.js/issues/2696

https://github.com/ropensci/plotly/issues/1194

So until this feature is added, I guess my question is what options are there to do this? Seems like such a basic feature, that I hope someone with more knowledge of JavaScript/Shiny/Plotly has hacked into.

like image 246
user3763801 Avatar asked Nov 07 '22 17:11

user3763801


1 Answers

Edit: The Plotly.plot() function has been deprecated - now using Plotly.update() instead:

Please check the following workaround based on this codepen I found via this question.

The following is using plotlyProxy instead of re-rendering the plot, which is faster:

library(plotly)
library(shiny)
library(htmlwidgets)

initDF <- data.frame(x = 1:10, y = 1:10)

ui <- fluidPage(
  plotlyOutput("myPlot"),
  verbatimTextOutput("click")
)

server <- function(input, output, session) {
  
  js <- "
    function(el, x, inputName){
      var id = el.getAttribute('id');
      var gd = document.getElementById(id);
      var d3 = Plotly.d3;
      Plotly.update(id).then(attach);
        function attach() {
          gd.addEventListener('click', function(evt) {
            var xaxis = gd._fullLayout.xaxis;
            var yaxis = gd._fullLayout.yaxis;
            var bb = evt.target.getBoundingClientRect();
            var x = xaxis.p2d(evt.clientX - bb.left);
            var y = yaxis.p2d(evt.clientY - bb.top);
            var coordinates = [x, y];
            Shiny.setInputValue(inputName, coordinates);
          });
        };
  }
  "
  
  clickposition_history <- reactiveVal(initDF)
  
  observeEvent(input$clickposition, {
    clickposition_history(rbind(clickposition_history(), input$clickposition))
  })
  
  output$myPlot <- renderPlotly({
    plot_ly(initDF, x = ~x, y = ~y, type = "scatter", mode = "markers") %>%
      onRender(js, data = "clickposition")
  })
  
  myPlotProxy <- plotlyProxy("myPlot", session)
  
  observe({
    plotlyProxyInvoke(myPlotProxy, "restyle", list(x = list(clickposition_history()$x), y = list(clickposition_history()$y)))
  })
  
  output$click <- renderPrint({
    clickposition_history()
  })
}

shinyApp(ui, server)

result

Related GitHub issue and PR.

Thanks @unumileappassionato for providing the solution regarding the small horizontal offset in my initial answer.

like image 89
ismirsehregal Avatar answered Nov 15 '22 06:11

ismirsehregal