Shiny in R: How can I fade-out my plotOutput from renderPlot if certain conditions are not met?

后端 未结 2 2109
盖世英雄少女心
盖世英雄少女心 2021-01-16 07:49

the question is straight forward. First, I tried an if-else condition within the render plot. Something like

if (input$Next > 0) {
   plot(...)
}
else {
          


        
相关标签:
2条回答
  • 2021-01-16 07:55
    1. First possibility - conditionalPanel

    We want to show the plotOutput if the actionButton was pressed. More specifically, if input.Next > 0. This condition is evaluated in javaScript, hence we have a slightly different syntax - instead of $ we use . after input and we use the parentheses.

    conditionalPanel(
          condition = "input.Next * 1 > 0",
          plotOutput("test")  
        )
    

      However, it is quite strange that we multiply input.Next by one. It is necessary because input.Next, expect a number, returns also attributes. It seems that JavaScript doesn't know how to deal with this...but the multiplication does the trick.

    [1] 0
    attr(,"class")
    [1] "integer"                "shinyActionButtonValue"
    

    In this example the plotOutput appears immediately...definitely too fast.

    library(shiny)
    
    ui1 <- shinyUI(fluidPage(
      sidebarPanel(
        conditionalPanel(
          condition = "input.Next * 1 > 0",
          plotOutput("test")  
        ),
        actionButton("Next", "Next")
      )
    ))
    
    
    server1 <- shinyServer(function(input, output, session) {
    
      output$test <- renderPlot({
        pt <- plot(input$Next, 2)
        print(input$Next)
        print(pt)
      })
    
    })
    
    shinyApp(ui1, server1)
    

    1. "Slowing down the train"

    In this example, we're going to "slow down" the speeding plotOutput. To do so we need the package shinyjs.

    First, we're going to wrap the conditionalPanel into a div with an id, say, animation

    div(id = "animation",
          conditionalPanel(
            condition = "input.Next * 1 > 0",
            plotOutput("test")  
          )
        )
    

    Then, on the server side, we're going to define the animation in the following way: conditional on the input$next the div should show up with the slide animation.

    observe({
            toggle(id = "animation", anim = TRUE, animType = "slide",
                  time = 0.5, condition = input$Next > 0)
          })
    

     

    Full example:

    ui2 <- shinyUI(fluidPage(
      # we need to include this function in order to use shinyjs functions
      useShinyjs(), 
    
      sidebarPanel(
        actionButton("Next", "Next"), 
    
        div(id = "animation",
            conditionalPanel(
              condition = "input.Next * 1 > 0",
              plotOutput("test"),
              sliderInput("manipulate", "slider", min = 0, max = 1, value = 1)
            )
        )
      )
    ))
    
    
    server2 <- shinyServer(function(input, output, session) {
    
      # Introduce gently the div with an id = "animation" and its all content.
      observe({
        toggle(id = "animation", anim = TRUE, animType = "slide",
               time = 0.5, condition = input$Next > 0)
      })
      # We could animate only the plotOutput with "toogle(id = test")" 
      # - it would work as well, but for the first time the plot is shown
      # way we would get an errors with margins.
    
    
      output$test <- renderPlot({
        #plot(input$Next, 2)
        ggplot(iris, aes(x = Species)) + geom_bar(alpha = input$manipulate)
    
      })
    })
    
    shinyApp(ui2, server2)
    

    1. renderUI

    As you pointed out, the another possibility is to use the function renderUI. If you want to render more than one element at once, you have to wrap them into a list as in the example below:

    library(shiny)
    library(ggplot2)
    
    ui3 <- shinyUI(fluidPage(
      sidebarPanel(
        uiOutput("dynamic"),
        actionButton("Next", "Next")
      )
    ))
    
    
    server3 <- shinyServer(function(input, output, session) {
    
      output$dynamic <- renderUI({
        if (input$Next > 0) {
          # if we want to render more element, we need the list
          list(
            plotOutput("test"),
            sliderInput("manipulate", "slider", min = 0, max = 1, value = 1)
          )
        }
      })
    
    
      output$test <- renderPlot({
        #plot(input$Next, 2)
        ggplot(iris, aes(x = Species)) + geom_bar(alpha = input$manipulate)
      })
    
    })
    
    shinyApp(ui3, server3)
    
    0 讨论(0)
  • 2021-01-16 08:09

    Use a conditional panel like so:

    library(shiny)
    ui =fluidPage(
      sidebarPanel(
        conditionalPanel(condition="input.Next>0",
        plotOutput("test")),
        actionButton("Next", "Next")
      ))
    
    server=shinyServer(function(input, output, session) {
    
        output$test <- renderPlot({
    
            req(input$Next > 0)
    
          pt <- plot(input$Next,2)
          print(pt)
        })
    
    })
    
    shinyApp(ui=ui,server=server)
    
    0 讨论(0)
提交回复
热议问题