15

I would like to have the shiny-plotly output height and width adjusted to the current window size. I have tried to use the below but of no use.

ShinyUi <- fluidPage(

  # Application title
  titlePanel("title"),

  sidebarLayout(
    sidebarPanel(
      ... inputs ...
    ),

    mainPanel(
          plotlyOutput("distPlot", height = 'auto', width = 'auto')
      )
  ))

ShinyServer <- function(input, output, session) {

   output$distPlot <- renderPlotly({

    p <- ggplot(dataShow, aes(x=dataShow$X, y=dataShow$Y))  + 
geom_point(shape=1, alpha = 0.5, color = "grey50")

    ggplotly(p)

  })

}


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

Would you know of any other options to use maybe in server function instead of the above UI function usage?

Smaller Window: enter image description here

Expanded Window:enter image description here

Prradep
  • 5,506
  • 5
  • 43
  • 84
  • are you already using `fluidPage()` ? – Tonio Liebrand Jun 02 '17 at 09:01
  • @BigDataScientist Please look at the code structure included in the updated post. – Prradep Jun 02 '17 at 09:16
  • What do you mean when you say `shiny-plotly output height and width adjusted to the current window size`? Do you want it do occupy certain ratio of your screen size? – SBista Jun 06 '17 at 05:44
  • @SBista It should resize according to the available window properties. Or in other words, it should occupy 75% of the window area all the time. For more clearer picture, I have added the figures both before and after increasing the browser window size. – Prradep Jun 06 '17 at 06:27
  • 2
    One way which is tedious and requires `js` would be to get the window size and pass it to `ggplotly` function. Refer to [this](https://stackoverflow.com/questions/36995142/get-the-size-of-the-window-in-shiny) link to get the window size. – SBista Jun 06 '17 at 06:38
  • @SBista I am looking for `renderPlotly` or `plotlyOutput` options. The mentioned sources are not useful in my case. – Prradep Jun 07 '17 at 11:20

2 Answers2

20

It does not answer your question but in line to my comments you can add the plot height and width to the ggplotly function using the js from this link.

I have prepared a minimal example of what you are want.

library(shiny)
library(plotly)

ShinyUi <- fluidPage(
  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("distPlot", width = "auto")

  )

ShinyServer <- function(input, output, session) {


  #To make the responsive to the change in UI size
  observeEvent(input$dimension,{

    output$distPlot <- renderPlotly({

      p <- ggplot(iris, aes(x = Sepal.Length, y=Sepal.Width))  +
        geom_point(shape=1, alpha = 0.5, color = "grey50")
      ggplotly(p, width = (0.95*as.numeric(input$dimension[1])), height = as.numeric(input$dimension[2]))

    })

  })

}


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

The output you get is as follows: enter image description here

Now when you make the window even smaller you still get a plot which occupies the whole screen (no scrollbars!) as follows: enter image description here

SBista
  • 7,479
  • 1
  • 27
  • 58
  • Yes, Thanks. Though it does not answer my question, it provided useful ways of achieving the solution. (If there is no another straightforward answer in next few days, I will accept this as a (workaround) answer.) – Prradep Jun 08 '17 at 14:31
  • I feel like he answered your question, for the most part. It doesn't look like the plotly library for R has a simple means for you to achieve this. His solution was more elegant than my own; yet to find something as good. – Joe Flack Apr 13 '21 at 00:09
1

Foreward

Please see the post by @SBista first.

I simply want to add to that response for a special use case: to lower the frequency of times Shiny attempts to re-render a visualization as the window is slowly resized by grabbing one of the edges of the window with the mouse and resizing that way. For me, render time took awhile, and without this additional code, it was doing several re-renders back to back from just one window resize.

Answer

Inside my ui.R I have a tags$script with the following JS string:

console.log("INFO: Loaded ui.R custom JS.");

// VARS
const REFRESH_RATE_MIN_SECONDS = 1.5;
var dimension = [0, 0];
var notRecentlyRendered = true;
var midRender = false;
var timeNow = Date.now();
var lastRendered;
var nowDiffMs;

// METHODS
$(document).on("shiny:connected", function(e) {
    dimension[0] = window.innerWidth;
    dimension[1] = window.innerHeight;
    Shiny.onInputChange("dimension", dimension);
})

$(window).resize(function(e) {
    timeNow = Date.now();
    firstRender = (typeof(lastRendered) === "undefined");

    if (firstRender === true) {
      nowDiffMs = timeNow - lastRendered;
      refreshRateMinMs = REFRESH_RATE_MIN_SECONDS * 1000;
      notRecentlyRendered = nowDiffMs > refreshRateMinMs;
    }

    if ((midRender === false) && (notRecentlyRendered === true)) {
      console.log("INFO: Adjusting figure height.");
      dimension[0] = window.innerWidth;
      dimension[1] = window.innerHeight;
      midRender = true;
      Shiny.onInputChange("dimension", dimension);
    }
})

In my server.R file I have my observable:

observeEvent(input$dimension,{
    output$multi_indicator_facility <- renderPlotly({
      plot.multi_indicator_facility(input)
})

In another file where I have plot.multi_indicator_facility(), which goes roughly as follows:

gg = ggplot(...)  # ... = a lot of code
ggp = ggplotly(gg, height=figure.height)  # I took figure.height from input$dimension
# More JS within R: 
ggp = onRender(
      ggp, '
      function(el) { 
        console.log("Rendered.");
        lastRendered = Date.now();
        midRender = false;
      }
    ')
return(ggp)

Also don't forget to include the htmlwidgets lib to use onRender.

library('htmlwidgets')  # <-- include this somewhere (e.g. server.R)
Joe Flack
  • 866
  • 8
  • 14