plot is stretched when window is resized
Describe the problem
If I create a plot with a width specified in renderPlot it works as expected when the page first renders. But if I resize the page the plot image is stretched to fill the whole space. If I generate a new plot it has the expected width again. In my actual use case this also happens after the first time an actionButton is pressed which is more problematic than if it only ever happened with window resizing.
library(shiny)
library(bslib)
# The with basic shiny behaves as expected
shinyApp(
ui = fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("newplot", "New plot")
),
mainPanel(
plotOutput("plot")
)
)
),
server = function(input, output) {
output$plot <- renderPlot({
input$newplot
# Add a little noise to the cars data
cars2 <- cars + rnorm(nrow(cars))
plot(cars2)
}, width = 400)
}
)
# with bslib it doesn't
shinyApp(
ui = page_sidebar(
sidebar = sidebar(
actionButton("newplot", "New plot")
),
page_fluid(
plotOutput("plot", fill = FALSE)
)
),
server = function(input, output) {
output$plot <- renderPlot({
input$newplot
# Add a little noise to the cars data
cars2 <- cars + rnorm(nrow(cars))
plot(cars2)
},
width = 400)
}
)
Before resize
After resize
Session Info
─ Session info ────────────────────────────────────────────────────────────────────────────────────────────────────
setting value
version R version 4.4.1 (2024-06-14 ucrt)
os Windows 11 x64 (build 22631)
system x86_64, mingw32
ui RStudio
language (EN)
collate English_United States.utf8
ctype English_United States.utf8
tz America/New_York
date 2024-10-29
rstudio 2024.09.0+375 Cranberry Hibiscus (desktop)
pandoc 3.2 @ C:/Program Files/RStudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)
─ Packages ────────────────────────────────────────────────────────────────────────────────────────────────────────
package * version date (UTC) lib source
bsicons 0.1.2 2023-11-04 [1] CRAN (R 4.4.1)
bslib * 0.8.0.9000 2024-10-29 [1] Github (rstudio/bslib@85b0428)
cachem 1.1.0 2024-05-16 [1] CRAN (R 4.4.1)
callr 3.7.6 2024-03-25 [1] CRAN (R 4.4.1)
cli 3.6.3 2024-06-21 [1] CRAN (R 4.4.1)
clipr 0.8.0 2022-02-22 [1] CRAN (R 4.4.1)
curl 5.2.1 2024-03-01 [1] CRAN (R 4.4.1)
desc 1.4.3 2023-12-10 [1] CRAN (R 4.4.1)
devtools 2.4.5 2022-10-11 [1] CRAN (R 4.4.1)
digest 0.6.36 2024-06-23 [1] CRAN (R 4.4.1)
ellipsis 0.3.2 2021-04-29 [1] CRAN (R 4.4.1)
evaluate 0.24.0 2024-06-10 [1] CRAN (R 4.4.1)
fansi 1.0.6 2023-12-08 [1] CRAN (R 4.4.1)
fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.4.1)
fs 1.6.4 2024-04-25 [1] CRAN (R 4.4.1)
glue 1.7.0 2024-01-09 [1] CRAN (R 4.4.1)
htmltools 0.5.8.1 2024-04-04 [1] CRAN (R 4.4.1)
htmlwidgets 1.6.4 2023-12-06 [1] CRAN (R 4.4.1)
httpuv 1.6.15 2024-03-26 [1] CRAN (R 4.4.1)
jquerylib 0.1.4 2021-04-26 [1] CRAN (R 4.4.1)
jsonlite 1.8.8 2023-12-04 [1] CRAN (R 4.4.1)
knitr 1.48 2024-07-07 [1] CRAN (R 4.4.1)
later 1.3.2 2023-12-06 [1] CRAN (R 4.4.1)
lifecycle 1.0.4 2023-11-07 [1] CRAN (R 4.4.1)
magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.4.1)
memoise 2.0.1 2021-11-26 [1] CRAN (R 4.4.1)
mime 0.12 2021-09-28 [1] CRAN (R 4.4.0)
miniUI 0.1.1.1 2018-05-18 [1] CRAN (R 4.4.1)
pillar 1.9.0 2023-03-22 [1] CRAN (R 4.4.1)
pkgbuild 1.4.4 2024-03-17 [1] CRAN (R 4.4.1)
pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.4.1)
pkgload 1.4.0 2024-06-28 [1] CRAN (R 4.4.1)
processx 3.8.4 2024-03-16 [1] CRAN (R 4.4.1)
profvis 0.3.8 2023-05-02 [1] CRAN (R 4.4.1)
promises 1.3.0 2024-04-05 [1] CRAN (R 4.4.1)
ps 1.7.7 2024-07-02 [1] CRAN (R 4.4.1)
purrr 1.0.2 2023-08-10 [1] CRAN (R 4.4.1)
R6 2.5.1 2021-08-19 [1] CRAN (R 4.4.1)
ragg 1.3.2 2024-05-15 [1] CRAN (R 4.4.1)
Rcpp 1.0.12 2024-01-09 [1] CRAN (R 4.4.1)
remotes 2.5.0 2024-03-17 [1] CRAN (R 4.4.1)
reprex 2.1.1 2024-07-06 [1] CRAN (R 4.4.1)
rlang 1.1.4 2024-06-04 [1] CRAN (R 4.4.1)
rmarkdown 2.27 2024-05-17 [1] CRAN (R 4.4.1)
rstudioapi 0.16.0 2024-03-24 [1] CRAN (R 4.4.1)
sass 0.4.9 2024-03-15 [1] CRAN (R 4.4.1)
sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.4.1)
shiny * 1.8.1.1 2024-04-02 [1] CRAN (R 4.4.1)
stringi 1.8.4 2024-05-06 [1] CRAN (R 4.4.0)
stringr 1.5.1 2023-11-14 [1] CRAN (R 4.4.1)
systemfonts 1.1.0 2024-05-15 [1] CRAN (R 4.4.1)
textshaping 0.4.0 2024-05-24 [1] CRAN (R 4.4.1)
tibble 3.2.1 2023-03-20 [1] CRAN (R 4.4.1)
urlchecker 1.0.1 2021-11-30 [1] CRAN (R 4.4.1)
usethis 3.0.0 2024-07-29 [1] CRAN (R 4.4.1)
utf8 1.2.4 2023-10-22 [1] CRAN (R 4.4.1)
vctrs 0.6.5 2023-12-01 [1] CRAN (R 4.4.1)
withr 3.0.1 2024-07-31 [1] CRAN (R 4.4.1)
xfun 0.45 2024-06-16 [1] CRAN (R 4.4.1)
xtable 1.8-4 2019-04-21 [1] CRAN (R 4.4.1)
yaml 2.3.10 2024-07-26 [1] CRAN (R 4.4.1)
[1] C:/Users/EndicottS/AppData/Local/Programs/R/R-4.4.1/library
──────────────────
I think this is the behavior you're looking for (the default width is 100%, so the behavior you're seeing seems expected)?
shinyApp(
ui = page_sidebar(
sidebar = sidebar(
actionButton("newplot", "New plot")
),
plotOutput("plot", width = 400, fill = FALSE)
),
server = function(input, output) {
output$plot <- renderPlot({
input$newplot
# Add a little noise to the cars data
cars2 <- cars + rnorm(nrow(cars))
plot(cars2)
},
width = 400)
}
)
That works for this example but in my actual use case I need to set the width on the server side using a function.
Here is a better reprex
shinyApp(
ui = page_sidebar(
sidebar = sidebar(
actionButton("newplot", "New plot")
),
plotOutput("plot", fill = FALSE)
),
server = function(input, output) {
counter <- reactiveValues(n = 1)
observeEvent(input$newplot, {
counter$n <- counter$n + 1
})
output$plot <- renderPlot({
input$newplot
# Add a little noise to the cars data
par(mfrow = c(1,counter$n))
for(i in 1:counter$n){
cars2 <- cars + rnorm(nrow(cars))
plot(cars2)
}
},
width = function(){
400*counter$n
})
}
)
In that case, you could set width = "auto" instead. But, I think what you really want is a different plotOutput("plot_i", width = 400) for each plot, then something like layout_column_wrap() to wrap the new plots onto new lines when needed.
No I want to adjust the width of the plot output based on the calculation I do on the server side and I want it to adjust appropriately to changes in window size like it does with basic shiny.
In my real example I am using a faceted ggplot bar chart and the user can add any number of scenarios and re-run the model which adds another facet to the ggplot plot. Therefore, I want to control the width of the plot so the bars are not super wide when there are not very many scenarios and I need to have it all in one plot with coordinated legend etc.
Here is an example of what my actual plot looks like:
In that case, you'll want a renderUI() that returns a plotOutput(width = 400*counter$n)
@cpsievert what you supplied is a useful workaround but I think that bslib is still not behaving as expected. Why doesn't it respect the width that is set it renderPlot in the way that shiny does? Is this difference documented somewhere?
I switched from plain shiny to access some of the awesome theming features that bslib has but it would be helpful if these sorts of differences were minimized and or explained.
That's true, I'm not sure we'd change the behavior at this point, but we could do more to document difference