【问题标题】:Animation/transition for Shiny conditionalPanelShiny conditionalPanel 的动画/过渡
【发布时间】:2020-07-19 21:17:23
【问题描述】:

闪亮的条件面板突然出现然后消失。有什么方法可以让它们滑动或褪色或以其他方式轻轻过渡?

【问题讨论】:

  • @史蒂夫,看我的编辑。我已经完成了一些 R 函数来帮助用户。不再需要用 JavaScript 编写代码。

标签: r shiny


【解决方案1】:

这是一种在元素显示时淡化元素的方法:

js <- "
$(document).ready(function(){
  $('#plotContainer').on('show', function(event){
    $(this).css('opacity', 0).animate({opacity: 1}, {duration: 1000});
  });
});
"

ui <- fluidPage(
  tags$head(tags$script(HTML(js))),
  sidebarPanel(
    actionButton("showplot", "Show")
  ),
  mainPanel(
    conditionalPanel(
      condition = "input.showplot > 0",
      id = "plotContainer",
      plotOutput("plot")
    )
  )
)

server <- function(input, output) {
  x <- rnorm(100)
  y <- rnorm(100)
  
  output$plot <- renderPlot({
    plot(x, y)
  })
}

shinyApp(ui, server)


编辑

还有对隐藏事件的影响:

js <- "
$(document).ready(function(){
  $('#plotContainer').on('show', function(){
    $(this).css('opacity', 0).animate({opacity: 1}, {duration: 1000});
  }).on('hide', function(){
    var $this = $(this);
    setTimeout(function(){
      $this.show().hide(1000);
    })
  });
});
"

ui <- fluidPage(
  tags$head(tags$script(HTML(js))),
  sidebarPanel(
    actionButton("showplot", "Show/Hide")
  ),
  mainPanel(
    conditionalPanel(
      condition = "input.showplot % 2 == 1",
      id = "plotContainer",
      plotOutput("plot")
    )
  )
)

server <- function(input, output) {
  x <- rnorm(100)
  y <- rnorm(100)
  
  output$plot <- renderPlot({
    plot(x, y)
  })
}

shinyApp(ui, server)


编辑

Animate.cssjQuery-animateCSS 库的有趣效果:

js <- "
$(document).ready(function(){
  $('#plotContainer').on('show', function(){
    var $this = $(this);
    $this.css('opacity', 0).
      animate({opacity: 1}, 500, function(){
        $this.animateCSS('jello', {
          delay: 0, 
          duration: 2000
        });
      });
  }).on('hide', function(){
    var $this = $(this);
    setTimeout(function(){
      $this.show().animateCSS('heartBeat', {
        delay: 0, 
        duration: 2000,
        callback: function(){$this.hide(500);}
      });
    }, 0);
  });
});
"

ui <- fluidPage(
  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"),
    tags$script(HTML(js))
  ),
  sidebarPanel(
    actionButton("showplot", "Show/Hide")
  ),
  mainPanel(
    conditionalPanel(
      condition = "input.showplot % 2 == 1",
      id = "plotContainer",
      plotOutput("plot")
    )
  )
)

server <- function(input, output) {
  x <- rnorm(100)
  y <- rnorm(100)
  
  output$plot <- renderPlot({
    plot(x, y)
  })
}

shinyApp(ui, server)


编辑

我已经完成了一些方便的 R 函数来将这些动画绑定到 Shiny 应用程序中。代码如下:

library(shiny)

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 = 600, onHide = NULL, fadeOut = 400){
    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, ...)
    tags$div(id=id, tagList(condPanel, script))
  }

您只能使用animateCSSanimatedConditionalPanelanimateCSS 函数定义了一个动画。您可以使用 then 参数链接动画。 animatedConditionalPanel 函数替换了 conditionalPanel。这是一个例子:

ui <- fluidPage(
  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")
  ),
  sidebarPanel(
    actionButton("showplot", "Show/Hide")
  ),
  mainPanel(
    animatedConditionalPanel(
      condition = "input.showplot % 2 == 0",
      onShow = animateCSS("swing", duration = 1000, then = animateCSS("jello")),
      fadeIn = 400,
      onHide = animateCSS("pulse", then = animateCSS("bounce")),
      plotOutput("plot")
    )
  )
)

server <- function(input, output) {
  x <- rnorm(100)
  y <- rnorm(100)

  output$plot <- renderPlot({
    plot(x, y)
  })
}

shinyApp(ui, server)

【讨论】:

  • 您能否解释一下上面最简单/第一个示例中不同代码行的作用?例如,我不明白这行:tags$head(tags$script(HTML(js))) 在做什么。我是否需要将相关元素标记为“头部”才能将动画应用于它们? “显示”是 js 的默认术语还是与闪亮操作按钮中的“显示”有关?
猜你喜欢
  • 2016-02-26
  • 2016-11-01
  • 1970-01-01
  • 2016-03-16
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多