问题
I have a shiny app with a title, one plot, some description and an actionButton. I want the elements to be aligned as follows:
- title on top;
- description and actionButton at the bottom;
- plot in between resizing according to the monitor resolution.
My app.R looks as follows:
library(shiny)
text <- list(
"one",
"one\ntwo",
"one\ntwo\nthree",
"one\ntwo\nthree\nfour"
)
ui <- fluidPage(
titlePanel("title"),
fluidRow(plotOutput("plot")),
fluidRow(style = "position:absolute;bottom:20px;left:20px",
verbatimTextOutput("text"),
actionButton("next_el", ">>")
)
)
server <- function(input, output) {
output$plot <- renderPlot({
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$next_el + 1)
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
output$text <- renderText(text[[input$next_el + 1]])
observeEvent(input$next_el, {})
}
# Run the application
shinyApp(ui = ui, server = server)
What I have at the moment: title, description and actionButton are placed ok on desktop and on mobile screens. description also resizes with the amount of text present.
However, the plot does not resize properly: On mobile devices the description is placed over the plot. On the other side on desktop devices the plot only uses about half the screen.
I tried resizing the plot with plotOutput("plot", height = "50%") and plotOutput("plot", height = "auto"), but then the plot disappears.
What can I do in order my plot resizes up if there's enough space and resizes down if there's not enough space?
回答1:
One way to approach this without additional css/html code is to set the height of the plot dynamically using the session$clientData object. Plot heights are set at a default value, but you can set the height to a dynamic value based on the plot width, which is responsive to the size of the browser window.
Updated server code would look like this:
server <- function(input, output, session) {
output$plot <- renderPlot({
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$next_el + 1)
hist(x, breaks = bins, col = 'darkgray', border = 'white')
}, height = function() {
if (session$clientData$output_plot_width <= 1000) {
(session$clientData$output_plot_width)*(3/4)
} else { (session$clientData$output_plot_width)*(7/16) }
})
output$text <- renderText(text[[input$next_el + 1]])
observeEvent(input$next_el, {})
}
where "plot" in output_plot_width matches the id of your plot.
You'll note that the code sets the plot height as a function of the width. You can change the aspect ratio by changing the fractions in the function. I also use two different aspect ratios, one for when the plot width is less than 1000 pixels (phones, tablets, etc.), and a different one when the user is more likely on a desktop or laptop screen.
To be fair, I haven't actually tested this on my phone - I just tested it using different window widths and aspect ratios in my browser.
来源:https://stackoverflow.com/questions/55244840/place-elements-in-shiny-app-in-order-they-resize-for-mobile-and-desktop-monito