reset animation in Shiny R Studio

2019-02-17 13:03发布

问题:

I am constructing an animated graph project using R Studio's Shiny. Currently the "Go !" button initiates the animation. I would like to have the "Reset" button re-initialize the variables and re-run the animation, but since Shiny does not allow within-code changes to the input$button values, I am stuck on how to do this. The real project is similar in form to the sample blocks below, but much more involved. Animation is integral to the information being conveyed. When the project is completed, I intend to deploy it on the Shiny server, so I would like users to be able to re-run the animation with different selections without having to re-open the link.

    #  ui.R
library(shiny)

shinyUI(fluidPage(

  # Application title
  headerPanel("Cost Explorer"),


  sidebarPanel(
    actionButton("goButton", "Go!"),
    actionButton("reset", "Reset"),

    sliderInput("myvar", label=h6("Variability of cost"),
                min=0, max=50, value=10)   
  ),

  mainPanel(

    plotOutput(outputId="tsplot")

  )
))

    # server.R
library(shiny)

shinyServer(function(input, output, session) {

  # initialize reactive values
  ts <- reactiveValues(cost=rep(NA,100), year=(2010:2109), counter=1)

  output$tsplot <- renderPlot({
    plot(ts$year, ts$cost, xlim=c(2010,2110), ylim=c(-200,200), xlab="Year",
         ylab="Cost (US Dollars)", type="l", main="Forecasted Cost Time series")
  })

  observe({

    isolate({


        if (ts$counter==1){
          ts$cost[ts$counter]=50 #initial cost
        }
        if (ts$counter > 1){
          ts$cost[ts$counter]=ts$cost[ts$counter-1]+rnorm(1,0,input$myvar)
        }
        ts$counter=ts$counter+1

    })

    if (((isolate(ts$counter) < 100)) & (input$goButton > 0)){
      invalidateLater(200, session)
    }
    if (input$reset > 0){
      # How do I add reset functionality?

    }
  }) 
})

回答1:

Based on your app it was quicker to add another observe and reset the counter to 1 using the global assignment operator <<-. Also I changed the plot so it is plots indexed variables. Have a look at similar problem people had, here. NB: In some of my apps I also have the pause button when a user presses the start button twice, you can achieve this by checking if the button index is divisible by two or not since every time the button is clicked it increments by one.

I was further looking into your app, make sure you are garbage collecting unreferenced observers, as you might run out of memory (look at the memory profile via Task manager). Look into this example here, alternately you can set-up a log-off functionality per session where the client will be logged off after n amount of minutes.

rm(list = ls())
library(shiny)

ui <- (fluidPage(
  # Application title
  headerPanel("Cost Explorer"),

  sidebarPanel(
    actionButton("goButton", "Go!"),
    actionButton("reset", "Reset"),
    sliderInput("myvar", label=h6("Variability of cost"),min=0, max=50, value=10)   
  ),
  mainPanel(plotOutput(outputId="tsplot"))
))

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

  # initialize reactive values
  ts <- reactiveValues(cost=rep(NA,100), year=(2010:2109), counter=1)

  output$tsplot <- renderPlot({
    plot(ts$year[1:ts$counter], ts$cost[1:ts$counter], xlim=c(2010,2110), ylim=c(-200,200), xlab="Year",
         ylab="Cost (US Dollars)", type="l", main="Forecasted Cost Time series")
  })

  observe({
    isolate({
      if (ts$counter==1){
        ts$cost[ts$counter]=50 #initial cost
      }
      if (ts$counter > 1){
        ts$cost[ts$counter]=ts$cost[ts$counter-1]+rnorm(1,0,input$myvar)
      }
      ts$counter=ts$counter+1    
    })
    if (((isolate(ts$counter) < 100)) & (input$goButton > 0)){
      invalidateLater(200, session)
    }

  })

  observe({
    if (input$reset > 0){
      ts$counter <<- 1
    }
  })
})

runApp(list(ui = ui, server = server))