Skip to content

sunburst plots: 'plotly_click' event_data only available for root and leafs #1648

Description

@ismirsehregal

Currently it seems that for sunburst plots the 'plotly_click' event_data is only available after clicking the root and leafs of the plot.

I'm wondering whether this behaviour is intentional and inherited by plotly.js or not.

Please see the following example and a workaround I came up with using onclick, which I first posted here:

library(plotly)
library(shinyjs)

DF <- structure(list(labels = c("total", "A", "C", "B", "F", "E", "F", 
                                "E", "D", "E", "D", "D", "F", "G", "H", "H", "G", "H", "G", "H", 
                                "H", "G", "I", "G", "I", "H", "G", "I", "I", "G", "G", "I", "H", 
                                "H", "I", "I", "I", "H", "I", "G"),
                     values = c(100L, 36L, 29L,
                                35L, 12L, 14L, 10L, 14L, 8L, 18L, 5L, 10L, 9L, 6L, 5L, 4L, 3L,
                                7L, 4L, 2L, 6L, 3L, 8L, 3L, 2L, 4L, 4L, 4L, 4L, 4L, 3L, 2L, 5L, 
                                5L, 2L, 2L, 1L, 1L, 1L, 5L),
                     parents = c(NA, "total", "total", "total", "total - A", "total - C", "total - C", "total - A",
                                 "total - B", "total - B", "total - C", "total - A", "total - B",
                                 "total - A - F", "total - C - E", "total - C - F", "total - A - E",
                                 "total - A - E", "total - B - D", "total - B - D", "total - B - E",
                                 "total - C - D", "total - B - E", "total - A - D", "total - B - D",
                                 "total - B - F", "total - C - F", "total - A - E", "total - C - E",
                                 "total - B - E", "total - B - F", "total - A - D", "total - A - D",
                                 "total - A - F", "total - B - F", "total - C - F", "total - C - D",
                                 "total - C - D", "total - A - F", "total - C - E"),
                     ids = c(
                       "total", "total - A", "total - C", "total - B", "total - A - F", "total - C - E", 
                       "total - C - F", "total - A - E", "total - B - D", "total - B - E", "total - C - D",
                       "total - A - D", "total - B - F", "total - A - F - G", "total - C - E - H",
                       "total - C - F - H", "total - A - E - G", "total - A - E - H", "total - B - D - G",
                       "total - B - D - H", "total - B - E - H", "total - C - D - G", "total - B - E - I",
                       "total - A - D - G", "total - B - D - I", "total - B - F - H", "total - C - F - G",
                       "total - A - E - I", "total - C - E - I", "total - B - E - G", "total - B - F - G",
                       "total - A - D - I", "total - A - D - H", "total - A - F - H", "total - B - F - I",
                       "total - C - F - I", "total - C - D - I", "total - C - D - H", "total - A - F - I",
                       "total - C - E - G"
                     )), row.names = c(NA,-40L), class = "data.frame")

ui <- fluidPage(
  useShinyjs(),
  plotlyOutput("sunburst"),
  htmlOutput("hoverDataOut"),
  htmlOutput("clickDataOut")
)

server <- function(input, output, session) {
  output$sunburst <- renderPlotly({
    plot_ly(data = DF, source = "sunSource", customdata = ~ids, ids = ~ids, labels= ~labels, parents = ~parents, values= ~values, type='sunburst', branchvalues = 'total')
  })
  
  hoverData <- reactive({
    currentEventData <- unlist(event_data(event = "plotly_hover", source = "sunSource", priority = "event"))
  })
  
  clickData <- reactiveVal()
  
  observe({
    clickData(unlist(event_data(event = "plotly_click", source = "sunSource", priority = "event")))
  })
  
  # workaround:
  # onclick(id = "sunburst", expr = {clickData(hoverData())})
  
  output$hoverDataOut <- renderText({
    paste("Hover data:", paste(names(hoverData()), unlist(hoverData()), sep = ": ", collapse = " | "))
  })
  
  output$clickDataOut <- renderText({
    paste("Click data:", paste(names(clickData()), unlist(clickData()), sep = ": ", collapse = " | "))
  })
  
}

shinyApp(ui, server)

screen

Activity

  1. dracodoc commented on Nov 6, 2019

    @dracodoc

    The zoom in/out of plotly sunburst chart is a great feature not seen in other similar sunburst chart implementations, however the missing event data on the zoom make it hard to use it in Shiny app. The workaround above is great using existing information, however if plotly itself can expose the data will be even better.

    By the way, for the purpose to get the center piece after chart zoom in/out, maybe it's better to comment out the line of
    observe({ clickData(unlist(event_data(event = "plotly_click", source = "sunSource", priority = "event"))) }), because when clicked on last level leaf, the plotly click event fired and was put into clickData. However this kind of click doesn't zoom the chart. With this commented out, the click data only update when non-last level leaf was clicked.

    User may also need to determine if the plot zoomed in or out by checking if the clicked piece is center, thus need to save last click data to compare.

  2. cpsievert commented on Nov 6, 2019

    @cpsievert
    Collaborator

    Thanks for reporting. This is a plotly.js bug. Follow plotly/plotly.js#4338 for progress.

  3. cpsievert commented on Nov 6, 2019

    @cpsievert
    Collaborator

    Oh, it's not a plotly.js bug...there is dedicated click event specifically for sunburst, plotly_sunburstclick. I just added support for that event in event_data().

  4. xhdong-umd commented on Nov 6, 2019

    @xhdong-umd

    I can understand they want to use a separate event, because when you click on end level leaf the click event is still fired when there is no zoom happening.

  5. dracodoc commented on Nov 7, 2019

    @dracodoc

    @cpsievert , the reason that I want to use this kind of event data is to get the current status of pie chart, especially the current center piece.

    With sunburstclick, I can know which piece is clicked, but I need the full click history to calculate which one is center piece:

    • clicking on same piece 1st time, zoom in and take it as center if this is not last leaf
    • clicking on it immediately in 2nd time, zoom out and center piece will be its parent
    • if clicked on last level leaf, nothing happen and take previous center piece
      ...

    This seemed too cumbersome. Do you think there is a better approach for this?

  6. cpsievert commented on Nov 7, 2019

    @cpsievert
    Collaborator

    I can know which piece is clicked, but I need the full click history to calculate which one is center piece:

    You'll have to store and manage this information using shiny::reactiveVal() or shiny::reactiveValues(). See this for example https://plotly-r.com/linking-views-with-shiny.html#reactive-vals

  7. dracodoc commented on Nov 7, 2019

    @dracodoc

    Yes I knew I can store the information. Just I was wondering if there is a better way, or if the information is actually available somewhere in the library, instead of calculating it and hope it don't loose track, once it loose track then everything will mess up...

  8. ismirsehregal commented on Nov 7, 2019

    @ismirsehregal
    Author

    Just use plotly_sunburstclick and filter/skip the leaf-clicks?

  9. dracodoc commented on Nov 7, 2019

    @dracodoc

    I think that's not enough, clicking on piece A first time will make it to be center, clicking it twice will make its parent to be center. Thus we need to track history to know the status.

  10. added a commit that references this issue on Mar 12, 2020
    32dde41
  11. added a commit that references this issue on Jun 26, 2022
    504c33f
  12. added a commit that references this issue on Jul 4, 2022
    55f49ee
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions