GL_Li
GL_Li

Reputation: 1798

ggplot2 and Shiny: how to scale the size of legend with figure size?

In ggplot2 the size of elements are specified separately. When the size of figure changes, the elements, for example the legend does not change. This could be a problem in Shiny when the size of output ggplot2 figures changes with browser window. Below is the code of a dummy Shiny app and two output figures at different browser window size. The smaller figure is ugly as part of its legend has been cut off.

Is there a method to scale the legend size with the figure size directly in ggplot2 without pre-saving the figure as an image file for Shiny apps?

library(shiny)
library(ggplot2)

ui <- fluidPage(
    br(), br(), br(),
    plotOutput("test", height = "auto")
)

server <- function(input, output, session) {
    output$test <- renderPlot(
        height = function() {
            0.8 * session$clientData$output_test_width
        },
        expr = {
            aaa <- ggplot(mtcars, aes(wt, mpg, color = cyl)) + 
                geom_point() + 
                theme(legend.position = c(0.9, 0.9))
            print(aaa)
        }
    )
}

shinyApp(ui, server)

The figure in a larger browser window looks good: enter image description here

But in small browser window, the top of the legend does not show up:

enter image description here

Upvotes: 12

Views: 2439

Answers (1)

eipi10
eipi10

Reputation: 93771

Here's a way to anchor the top of the legend so that it doesn't run off the top of the plot area. You just add legend.justification(0.5, 1) to the ggplot theme. The first value centers the x position of the legend. The second value "top justifies" the y position of the legend. (You can right-justify the legend by changing 0.5 to 1 for the first value, which will keep the legend from running off the right edge of the graph, if that's a problem.) This doesn't solve the relative sizing issue, but the full legend will always be visible and in the same location.

server <- function(input, output, session) {
  output$test <- renderPlot(
    height = function() {
      0.8 * session$clientData$output_test_width
    },
    expr = {
      aaa <- ggplot(mtcars, aes(wt, mpg, color = cyl)) + 
        geom_point() + 
        theme(legend.position = c(0.9, 0.98),
              legend.justification=c(0.5, 1))
      print(aaa)
    }
  )
}

Below I've inserted images of what this looks like in "small" and "large" browser windows.

enter image description here

enter image description here

Upvotes: 8

Related Questions