rBokeh dynamic plot size

638 Views Asked by At

I am trying to create an rBokeh plot as an output in my Shiny app with rbokehOutput('plot') in the ui and

output$plot <- renderRbokeh({ 
figure() %>%
      ly_hexbin(x,y)
    })

in the server part. I'd like the size of the plot to be dynamic in a sense that it should dynamically resize to fill the entire plot window. I've been playing with the height and width arguments, both in the ui and server parts, but have not been able to make it work; I also tried using sizing_mode = "stretch_both" in the server part. When I display the plot in RStudio without Shiny, the plot does not fill the entire plot window either, it keeps its square shape and aspect ratio. I would like it to behave like a normal R plot, i.e. when I enlarge the plot window, the plot automatically resizes to fill the full window. I found this link, but it only deals with Python implementation. Ideally, I would like the height in Shiny to be fixed at 500px and the width to change dynamically based on the (size of) browser.

Minimal working example:

library(shiny)
library(rbokeh)

ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      sliderInput('numpoint', 'Number of points to plot', min = 10, max = 1000, value = 200)
    ),
    mainPanel(
      rbokehOutput('plot', width = "98%", height = "500px")
    )
  )
)

server <- function(input, output) {
  output$plot <- renderRbokeh({
    x <- seq(1, 100, length = input$numpoint)
    y <- rnorm(input$numpoint, sd = 5)

    figure() %>%
      ly_hexbin(x,y)
  })
}

shinyApp(ui, server)

Updated MWE:

library(shiny)
library(rbokeh)

ui <- fluidPage(
  titlePanel("Hello Shiny!"),
  sidebarLayout(
    sidebarPanel(
      sliderInput('numpoint', 'Number of points to plot', min = 10, max = 1000, value = 200)
    ),
    mainPanel(
      fluidRow(
        column(12,
               rbokehOutput('plot', height = "800px")
               )
        ),
      fluidRow(
        column(12,
               plotOutput('plot1', height = "800px")
               )
      )

    )
  )
)

server <- function(input, output) {
  output$plot <- renderRbokeh({
    x <- seq(1, 100, length = input$numpoint)
    y <- rnorm(input$numpoint, sd = 5)

    figure(width = 1800, height = 800) %>%
      ly_hexbin(x,y)
  })

  output$plot1 <- renderPlot({
    x <- seq(1, 100, length = input$numpoint)
    y <- rnorm(input$numpoint, sd = 5)

    plot(x,y)
  })
}

shinyApp(ui, server)
2

There are 2 best solutions below

0
On

Inside of your ui body, you can add the following code:

# This will dynamically set the width of the rBokeh plots
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);
                          });
                          '))

Then you can use the dynamic size as an input oject like

figure(width = input$dimension[1], height = input$dimension[2],
4
On

Updating my answer..

I've added width and height into my call to figure() and the plot now re-sizes responsively.

library(shiny)
library(rbokeh)

ui <- fluidPage(
    titlePanel("Hello Shiny!"),
    sidebarLayout(
        sidebarPanel(
            sliderInput('numpoint', 'Number of points to plot', min = 10, max = 1000, value = 200)
    ),
    mainPanel(
        rbokehOutput('plot', width = "100%", height = "800px")
        )
    )
)

server <- function(input, output) {
    output$plot <- renderRbokeh({
        x <- seq(1, 100, length = input$numpoint)
        y <- rnorm(input$numpoint, sd = 5)

        figure(width = 1800, height = 800) %>%
            ly_hexbin(x,y)
    })
}

shinyApp(ui, server)

Is this what you wanted?