Get the size of the window in Shiny
See the example below. It uses Javascript to detect the browser window size (initial size and any resize), and use Shiny.onInputChange
to send the data to the server code for processing. It uses shiny:connected
event to get the initial window size, as Shiny.onInputChange
is not ready for use until shiny is connected.
library(shiny)
# Define UI for application that draws a histogram
ui <- shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
tags$head(tags$script('
var dimension = [0, 0];
$(document).on("shiny:connected", function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange("dimension", dimension);
});
$(window).resize(function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange("dimension", dimension);
});
')),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30)
),
# Show a plot of the generated distribution
mainPanel(
verbatimTextOutput("dimension_display"),
plotOutput("distPlot")
)
)
))
# Define server logic required to draw a histogram
server <- shinyServer(function(input, output) {
output$dimension_display <- renderText({
paste(input$dimension[1], input$dimension[2], input$dimension[2]/input$dimension[1])
})
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
})
# Run the application
shinyApp(ui = ui, server = server)
Utilizing Window Size Within Shiny Module
The issue is that input values accessed by modules are namespaced, while the input values set by Shiny.onInputChange
are not.
So in the myPlot
module, input$dimension
gets myPlot-dimension
but the input is actually just dimension
.
One solution would be to make the namespaced id available to the script:
library(shiny)
library(plotly)
myPlotUI <- function(id, label = "My Plot") {
ns <- NS(id)
dimensionId <- ns("dimension")
tagList(
tags$head(tags$script(sprintf("
var dimensionId = '%s';
var dimension = [0, 0];
$(document).on('shiny:connected', function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange(dimensionId, dimension);
});
$(window).resize(function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange(dimensionId, dimension);
});
", dimensionId))),
plotlyOutput(ns("myPlot"))
)
}
myPlot <- function(input, output, session) {
ns <- session$ns
output$myPlot <- renderPlotly({
plot_ly(midwest, x = ~percollege, color = ~state, type = "scatter",
width = (0.6 * as.numeric(input$dimension[1])),
height = (0.75 * as.numeric(input$dimension[2])))
})
}
server <- function(input, output, session){
callModule(myPlot, "myPlot")
}
ui <- fluidPage(
navlistPanel(
tabPanel("Dynamic Dimensions",
myPlotUI("myPlot"))
)
)
shinyApp(ui = ui, server = server)
Another solution that comes with a disclaimer: DANGER, undocumented, abuse-prone feature! You can actually get the root session from a module through session$rootScope()
. Would not recommend unless you really have to, but just FYI.
library(shiny)
library(plotly)
myPlotUI <- function(id, label = "My Plot") {
ns <- NS(id)
tagList(
tags$head(tags$script("
var dimension = [0, 0];
$(document).on('shiny:connected', function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange('dimension', dimension);
});
$(window).resize(function(e) {
dimension[0] = window.innerWidth;
dimension[1] = window.innerHeight;
Shiny.onInputChange('dimension', dimension);
});
")),
plotlyOutput(ns("myPlot"))
)
}
myPlot <- function(input, output, session) {
ns <- session$ns
rootInput <- session$rootScope()$input
output$myPlot <- renderPlotly({
plot_ly(midwest, x = ~percollege, color = ~state, type = "scatter",
width = (0.6 * as.numeric(rootInput$dimension[1])),
height = (0.75 * as.numeric(rootInput$dimension[2])))
})
}
server <- function(input, output, session){
callModule(myPlot, "myPlot")
}
ui <- fluidPage(
navlistPanel(
tabPanel("Dynamic Dimensions",
myPlotUI("myPlot"))
)
)
shinyApp(ui = ui, server = server)
In shiny, is it possible to get the size of an ui element in the server?
I found out that you can indeed access some information about the ui from the server.
To answer the question, you can get the width and height of an element created with plotOutput("plot1")
using session$clientData[["output_plot1_width"]]
and session$clientData[["output_plot1_height"]]
.
To get an exhaustive list of what info is available in a given session, go in debug-mode in a reactive expression in server.R
(for instance in renderText()
and type reactiveValuesToList(session$clientData)
.
Layout shiny app to set heights of elements to add up to 100% of window size
Add a height argument to your plotOutput
s with 30vh
(vertical height, essentially % of container). You can mess with the value to get it exactly where you want. More info on vh
here.
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot", height = '30vh'),
plotOutput("distPlot2", height = '30vh'),
plotOutput("distPlot3", height = '30vh')
)
Scaling shiny plots to window height
Use CSS3. Declare your height in viewport units http://caniuse.com/#feat=viewport-units .
You should be able to declare them using the height
argument in plotOutput
however shiny::validateCssUnit
doesnt recognise them so you can instead declare them in a style header:
library(shiny)
runApp(
list(server= function(input, output) {
output$myplot <- renderPlot({
hist(rnorm(1000))
})
}
, ui = pageWithSidebar(
headerPanel("window height check"),
sidebarPanel(
tags$head(tags$style("#myplot{height:100vh !important;}"))
),
mainPanel(
plotOutput("myplot")
)
)
)
)
This wont work in the shiny browser but should work correctly in a main browser.
Related Topics
Configuration Failed Because Libcurl Was Not Found
Create Barplot from Data.Frame
In Read.Table(): Incomplete Final Line Found by Readtableheader
Shiny Dashboard - Display a Dedicated "Loading.." Page Until Initial Loading of the Data Is Done
How to Select Non-Numeric Columns Using Dplyr::Select_If
Using Dplyr Within a Function, Non-Standard Evaluation
Get the Event Which Is Fired in Shiny
Weird Error in R When Importing (64-Bit) Integer with Many Digits
Update a Dataset After Putting a New Value in the Dt::Datatable
"Adding Missing Grouping Variables" Message in Dplyr in R
How to Output Text to the R Console in Color
How to Have Na's Displayed First Using Arrange()
Union of Intersecting Vectors in a List in R
How to Create a World Map in R with Specific Countries Filled In