Adicionando loaders ao seu Shiny app

É muito comum termos visualizações no nosso app que demoram para serem geradas. Quando estamos carregando o app, isso pode fazer com que parte da UI fique em branco, parecendo que a página está quebrada ou fazendo com que alguém passe em branco pelo output que tivemos tanto trabalho para fazer. Quando a visualização está sendo recalculada, o padrão do Shiny é deixar a versão anterior acizentada até que a nova apareça, o que pode gerar estranheza e também passar a ideia de que o aplicativo quebrou.

É uma boa prática sempre avisarmos a quem estiver usando o app que alguma coisa está acontecendo por trás das cortinas. Quando a espera é muito longa, devemos sempre que possível explicar o porquê a pessoa está esperando e dar uma estimativa do tempo. Nesses casos, barras de carregamento são a melhor alternativa. Falaremos delas em um outro post.

Quando a espera não é tão grande (entre 2 e 10 segundos, por exemplo), animações giratórias ou de looping infinito podem ser utilizadas para indicar que algo vai aparecer ali e reduzir um pouco a percepção do tempo de espera.

Neste post, falaremos de dois pacotes que deixam muito simples a tarefa de incluir essas animações em nossos outputs: o shinycssloaders e o shinyWidgets.

Se você ainda não tem esses pacotes instalados, ambos estão no CRAN:

install.packages("shinycssloaders")
install.packages("shinyWidgets")

O shinycssloaders é um pacote mantido pelo Dean Attali que possui uma única função: withSpinner(). Para colocar a animação de carregamento em uma visualização, basta colocar a função *Output() dentro da função withSpinner()! Sempre que ela estiver sendo calculada, um spinner será mostrado no lugar.

Rode o Shiny app abaixo para ver um exemplo:

library(shiny)

ui <- fluidPage(
  titlePanel("Exemplo shinyWidgets::addSpinner"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "variavel",
        label = "Escolha uma variável",
        choices = names(mtcars)
      )
    ),
    mainPanel(
      shinycssloaders::withSpinner(
        plotOutput(outputId = "histograma"),
        type = 4,
        color = "orange",
        size = 2
      )
    )
  )
)

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

  output$histograma <- renderPlot({
    Sys.sleep(5)
    hist(mtcars[[input$variavel]])
  })


}

shinyApp(ui, server)

Além de 8 opções de animações diferentes, que você pode trocar com o argumento type, também é possível ajustar o tamanho, a cor, a cor de fundo e até usar uma imagem própria como animação1.

Veja aqui um Shiny app que apresenta todas as opções de customização do shinycssloaders.

O pacote shinyWidgets é mantido pelo pessoal da dreamRs e possui diversos widgets muito úteis (falaremos bastante desse pacote em próximos posts). Adicionamos animações de carregamento utilizando a função addSpinner() e, assim como a função shinycssloards::withSpinner(), basta embrulhar suas funções *Output() com a função addSpinner().

São 9 opções de animação, escolhidas por meio do argumento spin. Aqui podemos customizar apenas a cor delas. Rode o app a seguir para ver um exemplo.

library(shiny)

ui <- fluidPage(
  titlePanel("Exemplo shinyWidgets::addSpinner"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "variavel",
        label = "Escolha uma variável",
        choices = names(mtcars)
      )
    ),
    mainPanel(
      shinyWidgets::addSpinner(
        plotOutput(outputId = "histograma"),
        spin = "cube",
        color = "purple"
      )
    )
  )
)

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

  output$histograma <- renderPlot({
    Sys.sleep(5)
    hist(mtcars[[input$variavel]])
  })


}

shinyApp(ui, server)

É isso! Dúvidas, sugestões e críticas, mande aqui nos comentários.

Até a próxima!


  1. Pode ser uma imagem estática ou GIF.↩︎

comments powered by Disqus