Reputation: 5696
I would like to have the height and width of the plotlyOutput
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?
Upvotes: 16
Views: 14896
Reputation: 33417
We can simply use relative css units:
library(shiny)
library(plotly)
ui <- fluidPage(
plotlyOutput("plot", width = "90vw", height = "90vh")
)
server <- function(input, output, session) {
output$plot <- renderPlotly({plot_ly(x = 1:10, y = 1:10, type = "scatter", mode = "lines+markers")})
}
shinyApp(ui, server)
Upvotes: 4
Reputation: 974
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.
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)
Upvotes: 1
Reputation: 7704
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:
Now when you make the window even smaller you still get a plot which occupies the whole screen (no scrollbars!) as follows:
Upvotes: 20