Scaling Shiny Plots to Window Height

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.

Sample Image

Scale and size of plot in RStudio shiny

Not sure if this gives you fully what you desire, but here's what worked for me.

The options specified in Server.R did take effect. (I just plotted two graphs of different sizes each.) I also took @Manetheran's suggestion and made cex and cex.axis into parameters. They seem to be working.

Below is the code for the full app, plus one screen shot.

###UI.R
shinyUI(pageWithSidebar(

headerPanel("Title"),

sidebarPanel(
sliderInput(inputId = "opt.cex",
label = "Point Size (cex)",
min = 0, max = 2, step = 0.25, value = 1),
sliderInput(inputId = "opt.cexaxis",
label = "Axis Text Size (cex.axis)",
min = 0, max = 2, step = 0.25, value = 1)
),

mainPanel(
plotOutput(outputId = "main_plot", width = "100%"),
plotOutput(outputId = "main_plot2", width = "100%")
)
))


###Server.R
shinyServer(function(input, output) {

x <- 1:10
y <- x^2

output$main_plot <- renderPlot({
plot(x, y)}, height = 200, width = 300)

output$main_plot2 <- renderPlot({
plot(x, y, cex=input$opt.cex, cex.lab=input$opt.cexaxis) }, height = 400, width = 600 )
} )

Sample Image

Update re. the Width=100% option in UI.R

Yes, in my case it definitely makes a difference. In the two lines below, new_main_plot and new_main_plot2 are identical, but they were rendered with different sizes. So the width option does take effect.

 mainPanel(
plotOutput(outputId = "new_main_plot", width = "100%"),
plotOutput(outputId = "new_main_plot2", width = "25%")
)

Hope that helps.

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)

Scaling plotOutput height to fill the row in a sidebarLayout

We can use jQuery to track the height of the sidebar and set the height of the plot in css before creating the plotOutput. To do that, we need to use uiOutput in the UI, then render the plot dynamically.

So in the UI, the mainPanel will now have:

uiOutput("ridgePlot")

Then the plot is rendered in the server like so:

output$ridgePlot <- renderUI({

# plot data
output$ridges <- renderPlot({

# plot()

})

plotOutput("ridges")

})

Now we use shinyjs() to write a simple javascript function that sets the height value of the plot to the height of the sidebar. The sidebar is of class well, so we first get the height of the well, save it to a variable then set the ridges plot to the height of the variable, in javascript like this:

var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)

I have used .outerHeight() because the well has extra padding that effectively gives it extra height than the height specified in the css rules for the well.

We can use this function in shiny using runjs() from shinyjs package. Since we need to get the height from the well after it has been rendered, we use observe and use it before the plotOutput inside the renderPlot, which is also inside the renderUI.

    observe({
session$onFlushed(function() {
shinyjs::runjs("var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)")
}, once=TRUE)
})

Putting it together in one Shiny app:

library(shiny)
library(shinyjs)
library(ggplot2)

ui = fluidPage(
useShinyjs(),
titlePanel("This is just a test!"),
sidebarLayout(

sidebarPanel(
uiOutput("ridgeDates")
),

mainPanel(
uiOutput("ridgePlot")
))
)

server = function(input, output, session) {

output$ridgeDates <- renderUI({

rng <- round(runif(1, 15, 21))

radioButtons("choose", "A changing list", choices = 1:rng)

})


output$ridgePlot <- renderUI({
datax <- matrix(c(1,2,3,4,5,6),6,1)
datay <- matrix(c(1,7,6,4,5,3),6,1)
titleplot<-"title"
summary <- "testing text"


output$ridges <- renderPlot({
# pl <- plot(datax, datay, main = titleplot, xlab = "input$axis1", ylab = "input$axis2", pch=18, col="blue")

ggplot(NULL, aes(datax, datay))+
geom_point(colour = "#1e90ff")

})

observe({
session$onFlushed(function() {
shinyjs::runjs("var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)")
}, once=TRUE)
})


plotOutput("ridges")


})

}

# Run the application
shinyApp(ui = ui, server = server)

My example:

Sample Image

Shiny: Dynamic height adjustment of plot

You can adjust the height in the renderPlot. I have set the minimum to 3 value box height. So, it starts increasing the height after you add 3 value boxes. You can modify it, as necessary. Try the code below.

  library(shiny)
library(shinydashboard)

ui <- dashboardPage(
dashboardHeader(),

dashboardSidebar(
selectizeInput(
inputId = "select",
label = "Select country:",
choices = c("CH", "JP", "GER", "AT", "CA", "HK"),
multiple = TRUE)
),

dashboardBody(
fluidRow(column(2, uiOutput("ui1")),
column(10, plotOutput("some_plot"))))#,

# column(4, uiOutput("ui2")),
# column(4, uiOutput("ui3")))
)

server <- function(input, output) {
plotht <- reactiveVal(360)
observe({
req(input$select)
nvbox <- length(input$select)
if (nvbox > 3) {
plotheight <- 360 + (nvbox-3)*120
}else plotheight <- 360
plotht(plotheight)
})

output$ui1 <- renderUI({
req(input$select)

lapply(seq_along(input$select), function(i) {
fluidRow(
valueBox(value = input$select[i],
subtitle = "Box 1",
width = 12)
)
})
})

observe({
output$some_plot <- renderPlot({
plot(iris)
}, height=plotht())
})


}

shinyApp(ui = ui, server = server)


Related Topics



Leave a reply



Submit