I'm plotting a barplot in ggplot2 in a shiny application.
What I would like is that when the mouse hovers over one of the bars, the bar becomes highlighted (maybe by a stronger outline) and when I click (or doubleclick) the bar, the corresponding x-value becomes available to be used as input for a textOutput
.
I tried to find examples on the shiny documentation, but there it's mostly about returning x-, y-values from the pointer location. Is there an example I could use as a starting point?
I had the same question and found this post. I realised the question is quite old, but maybe someone is still interested in a solution.
Challenge:
The problem you are facing is that the ggplot will be rendered as an image:
So you dont have seperate html elements you could listen on.
Solution:
But there is one interesting feature in ggplots in shiny. If you add a click listener to the plot, the $x
variable of the click event is scaled to the amount of elements in the picture. So if you add an onlick
listener the round($click$x)
will equal the element being clicked.
See an example here: https://shiny.rstudio.com/articles/plot-interaction-advanced.html
Reproducible example:
I implemented a solution with textbox and highlighting, with the highlighting part coming from Highlight a single "bar" in ggplot.
Solution looks as follows:
Sample data:
letters <- data.frame(
word = c("First", "Second", "Third"),
num = c(2, 3, 4),
stringsAsFactors = FALSE
)
The app:
library(shiny)
library(ggplot2)
ui <- fluidPage(
fluidRow(
column(6,
plotOutput("plot1", click = "plot1_click")
),
column(5,
uiOutput("text")
)
)
)
server <- function(input, output) {
global <- reactiveValues(toHighlight = rep(FALSE, length(letters$word)),
selectedBar = NULL)
observeEvent(eventExpr = input$plot1_click, {
global$selectedBar <- letters$word[round(input$plot1_click$x)]
global$toHighlight <- letters$word %in% global$selectedBar
})
output$plot1 <- renderPlot({
ggplot(data = letters, aes(x = word, y = num, fill = ifelse(global$toHighlight,
yes = "yes", no = "no"))) +
geom_bar(stat="identity") +
scale_fill_manual(values = c("yes" = "blue", "no" = "grey" ), guide = FALSE )
})
output$text <- renderUI({
req(global$selectedBar)
textInput(inputId = "label", label = "selected text:", value = global$selectedBar)
})
}
shinyApp(ui, server)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With