Here is an idea. Keep the plot as a reactiveValue
and have an observer to update the plot with user inputs. Then, have another observer to watch the plot data that will render the plot when the plot data changes. This way the long calculations happen before the plot data is changed, so the rendering of the plot should happen so quickly that there should be very little visible interrupt. Here is an example using the diamond
dataset from ggplot2
which is large enough to be obviously slow when rendering paths.
shinyApp(
shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("x", "X", choices=names(diamonds)),
selectInput("y", "Y", choices=names(diamonds)),
checkboxInput("line", "Add line")
),
mainPanel(
plotOutput("plot")
)
)
)
),
shinyServer(function(input, output, session) {
data(diamonds)
vals <- reactiveValues(pdata=ggplot())
observe({
input$x; input$y; input$line
p <- ggplot(diamonds, aes_string(input$x, input$y)) + geom_point()
if (input$line)
p <- p + geom_line(aes(group=cut))
vals$pdata <- p
})
observeEvent(vals$pdata,{
output$plot <- renderPlot({
isolate(vals$pdata)
})
})
## Compare to this version
## output$plot <- renderPlot({
## vals$pdata
## })
})
)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…