0

I want some animation on my conditionalpanels. I've found the solution provided here: Animation/transition for Shiny conditionalPanel. This is a following of another question (Animation on conditionalpanel).

The problem is shown in the image below:

enter image description here

Two problems:

  1. When I put another conditionalpanel (also a simple one) inside the animated, every time is triggered the inside condition, the animation of the bigger box is animated again.
  2. When I change from step two to step one, nothing is displayed. (I have to click on Next and then on Previous).

Here's a reproducible example:

library(shiny)
library(shinyjs)
library(shinydashboard)


animateCSS <- function(effect, delay = 0, duration = 500, then = NULL){
  effect <- match.arg(effect, c(
    "bounce",
    "flash",
    "pulse",
    "rubberBand",
    "shakeX",
    "shakeY",
    "headShake",
    "swing",
    "tada",
    "wobble",
    "jello",
    "heartBeat",
    "backInDown",
    "backInLeft",
    "backInRight",
    "backInUp",
    "backOutDown",
    "backOutLeft",
    "backOutRight",
    "backOutUp",
    "bounceIn",
    "bounceInDown",
    "bounceInLeft",
    "bounceInRight",
    "bounceInUp",
    "bounceOut",
    "bounceOutDown",
    "bounceOutLeft",
    "bounceOutRight",
    "bounceOutUp",
    "fadeIn",
    "fadeInDown",
    "fadeInDownBig",
    "fadeInLeft",
    "fadeInLeftBig",
    "fadeInRight",
    "fadeInRightBig",
    "fadeInUp",
    "fadeInUpBig",
    "fadeInTopLeft",
    "fadeInTopRight",
    "fadeInBottomLeft",
    "fadeInBottomRight",
    "fadeOut",
    "fadeOutDown",
    "fadeOutDownBig",
    "fadeOutLeft",
    "fadeOutLeftBig",
    "fadeOutRight",
    "fadeOutRightBig",
    "fadeOutUp",
    "fadeOutUpBig",
    "fadeOutTopLeft",
    "fadeOutTopRight",
    "fadeOutBottomRight",
    "fadeOutBottomLeft",
    "flip",
    "flipInX",
    "flipInY",
    "flipOutX",
    "flipOutY",
    "lightSpeedInRight",
    "lightSpeedInLeft",
    "lightSpeedOutRight",
    "lightSpeedOutLeft",
    "rotateIn",
    "rotateInDownLeft",
    "rotateInDownRight",
    "rotateInUpLeft",
    "rotateInUpRight",
    "rotateOut",
    "rotateOutDownLeft",
    "rotateOutDownRight",
    "rotateOutUpLeft",
    "rotateOutUpRight",
    "hinge",
    "jackInTheBox",
    "rollIn",
    "rollOut",
    "zoomIn",
    "zoomInDown",
    "zoomInLeft",
    "zoomInRight",
    "zoomInUp",
    "zoomOut",
    "zoomOutDown",
    "zoomOutLeft",
    "zoomOutRight",
    "zoomOutUp",
    "slideInDown",
    "slideInLeft",
    "slideInRight",
    "slideInUp",
    "slideOutDown",
    "slideOutLeft",
    "slideOutRight",
    "slideOutUp"
  ))
  js <- paste(
    "    $this.animateCSS('%s', {",
    "      delay: %d,",
    "      duration: %d,",
    "      callback: function(){",
    "        %s",
    "      }",
    "    });",
    sep = "\n"
  )
  sprintf(js, effect, delay, duration, ifelse(is.null(then), "", then))
}

onShowJS <- function(animation, fadeDuration){
  sprintf(paste(
    "$('#%%s>div').on('show', function(){",
    "  var $this = $(this);",
    "  $this.css('opacity', 0).animate({opacity: 1}, %d, function(){",
    animation,
    "  });",
    "});",
    sep = "\n"
  ), fadeDuration)
}

onHideJS <- function(animation, fadeDuration){
  paste(
    "$('#%s>div').on('hide', function(){",
    "  var $this = $(this);",
    "  setTimeout(function(){",
    sub(
      "^(\\s.*?\\$this\\.animateCSS)",
      "$this.show().animateCSS",
      sub(
        "\\{\n        \n      \\}",
        sprintf("{$this.hide(%d);}", fadeDuration),
        animation
      )
    ),
    "  }, 0);",
    "});",
    sep = "\n"
  )
}

animatedConditionalPanel <-
  function(condition, ..., onShow = NULL, fadeIn = 0, onHide = NULL, fadeOut = 0){
    id <- paste0("animateCSS-", stringi::stri_rand_strings(1, 15))
    jsShow <- ifelse(!is.null(onShow), sprintf(onShowJS(onShow, fadeIn), id), "")
    jsHide <- ifelse(!is.null(onHide), sprintf(onHideJS(onHide, fadeOut), id), "")
    script <- tags$script(HTML(paste(jsShow,jsHide,sep="\n")))
    condPanel <- conditionalPanel(condition, style = "display: none", ...)
    tags$div(id=id, tagList(condPanel, script))
  }

ui <- dashboardPage(
  header = dashboardHeader(title = "test"),
  sidebar = dashboardSidebar(),
  shinydashboard::dashboardBody(
    fluidPage(
      useShinyjs(),
      
      tags$head(
        tags$link(rel = "stylesheet", href = "https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.0/animate.compat.min.css"),
        tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/animateCSS/1.2.2/jquery.animatecss.min.js")
      ),
      
      fluidRow(
        textOutput("test"),
        column(2, offset = 2, actionButton("prev_box", "Previous")),
        column(
          4,
          
          animatedConditionalPanel(
            condition = "output.phase_box_ui == 0",
            onShow = animateCSS("backInRight", duration = 1000),
            onHide = animateCSS("backOutLeft", duration = 1000),
            fadeIn = 0,
            fadeOut = 0,
            uiOutput("box_move1")
          ),
          animatedConditionalPanel(
            condition = "output.phase_box_ui == 1",
            onShow = animateCSS("backInRight", duration = 1000),
            onHide = animateCSS("backOutLeft", duration = 1000),
            fadeIn = 0,
            fadeOut = 0,
            uiOutput("box_move2")
          )
          
        ),
        column(2, actionButton("next_box", "Next"))
      )
    )
  )
)

server <- function(input, output,session) {
  
  #### TEST BOX MOVING
  
  phase_box = reactiveVal(0)
  
  observeEvent(phase_box(),{
    if(phase_box() == 0){
      shinyjs::hide("prev_box")
    }else{
      shinyjs::show("prev_box")
    }
  })
  
  
  observeEvent(input$prev_box,{
    if(phase_box() > 0){
      val = phase_box() - 1
      phase_box(val)
    }
  })
  
  observeEvent(input$next_box,{
    if(phase_box() < 6){
      val = phase_box() + 1
      phase_box(val)
    }
  })
  
  output$test = renderText({
    phase_box()
  })
  
  output$phase_box_ui = reactive({return(phase_box())})
  outputOptions(output, "phase_box_ui", suspendWhenHidden = F)
  
  
  
  output$box_move1 = renderUI({
    box(width = NULL, status = "primary", solidHeader = T, title = "First box",
      h4(strong("This is the first box")),
      selectInput("step2", "Choose a step:", choices = c("one", "two")),
      br(),
      conditionalPanel(style = "display: none",
        condition = "input.step2 == 'two'",
        h4(strong("2. This is the second step"))
      )
    )
  })
  
  
  output$box_move2 = renderUI({
    box(width = NULL, status = "primary", solidHeader = T, title = "Second box",
    h4("This is the second box"))
  })
  
}

shinyApp(ui, server)
Fabio DR
  • 89
  • 10
  • 1
    Are you aware of library([shinyglide](https://github.com/juba/shinyglide)) or library([slickR](https://github.com/yonicd/slickR))? – ismirsehregal Sep 12 '22 at 07:22
  • Not at all! Shinyglide is fantastic! The cherry on top would be to customize the animation too, but I'm already greatly satisfied. Thank you a lot! – Fabio DR Sep 12 '22 at 12:50

0 Answers0