Search code examples
rshinyslickr

R Shiny: Relative size of images with slickR


Using a Shiny app, I would like to implement a slider with slickR to switch from one image to the other.

I managed to implement the slider but I'm having trouble in displaying the images correctly because of their different sizes. In the following example, the stackexchange logo is way bigger than the stackoverflow logo. When displaying them with slickR(), the bigger logo makes inroads into the first one like this:

enter image description here

I would also like to have the size of the pictures relative to the size of the screen.

Here is a reproducible example of the Shiny app used to generate the above image:

library(shiny)
library(slickR)

# User interface ----
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      
    ),
    
    mainPanel(
      slickROutput("slickr", width = "auto")
    )
  )
)

# Server ----
server <- function(input, output) {
  
  imgs_links <- list(
    "https://upload.wikimedia.org/wikipedia/fr/9/95/Stack_Overflow_website_logo.png",
    "https://upload.wikimedia.org/wikipedia/commons/6/6f/Stack_Exchange_Logo.png")
  
  output$slickr <- renderSlickR({
    
    photo_list <- lapply(imgs_links, function(x){
      tags$div(
        tags$img(src = x, width = "10%", height = "10%")
      )
    })
    
    imgs <- do.call(tagList, photo_list)
    slickR(imgs)
  })
}

# Run the application ----
shinyApp(ui = ui, server = server)

What would be the correct way to have each image resized according the size of the screen?


Solution

  • I don't manage to get it with the 'slickR' package. Here is a solution which doesn't use this package, it uses the 'slick' JavaScript library. You have to download the library files and put them in the www/slick-1.8.1/slick folder.

    library(shiny)
    
    ui <- fluidPage(
      tags$head(
        tags$link(rel="stylesheet", type="text/css",
                  href="slick-1.8.1/slick/slick-theme.css"),
        tags$link(rel="stylesheet", type="text/css",
                  href="slick-1.8.1/slick/slick.css"),
        tags$script(type="text/javascript", 
                    src="slick-1.8.1/slick/slick.js"),
        tags$script(HTML(
          "$(document).ready(function(){
      $('#images').slick({
        arrows: true,
        dots:true
      });
    });")),
        tags$style(HTML(
          "#images .slick-prev {
        position:absolute;
      top:65px; 
      left:-50px;
    }
    #images .slick-next {
      position:absolute;
      top:95px; 
      left:-50px;
    }
    .slick-prev:before, .slick-next:before { 
        color:red !important;
        font-size: 30px;
    }
    .content {
        margin: auto;
        padding: 2px;
        width: 90%;
    }"))
      ),
      
      sidebarLayout(
        
        sidebarPanel(
          ####
        ),
        
        mainPanel(
          tags$div(
            class = "content",
            tags$div(
              id = "images", 
              tags$img(
                src = "https://upload.wikimedia.org/wikipedia/fr/9/95/Stack_Overflow_website_logo.png",
                width = "50vw"
              ),
              tags$img(
                src = "https://upload.wikimedia.org/wikipedia/commons/6/6f/Stack_Exchange_Logo.png",
                width = "50vw"
              )
            )
          )
        )
      )
    )
    
    server <- function(input, output) {
      
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)
    

    enter image description here


    EDIT: dynamic number of images

    library(shiny)
    
    ui <- fluidPage(
      tags$head(
        tags$link(rel="stylesheet", type="text/css",
                  href="slick-1.8.1/slick/slick-theme.css"),
        tags$link(rel="stylesheet", type="text/css",
                  href="slick-1.8.1/slick/slick.css"),
        tags$script(type="text/javascript", 
                    src="slick-1.8.1/slick/slick.js"),
        tags$style(HTML(
          "#carousel .slick-prev {
        position:absolute;
      top:65px; 
      left:-50px;
    }
    #carousel .slick-next {
      position:absolute;
      top:95px; 
      left:-50px;
    }
    .slick-prev:before, .slick-next:before { 
        color:red !important;
        font-size: 30px;
    }
    .content {
        margin: auto;
        padding: 2px;
        width: 90%;
    }"))
      ),
      
      sidebarLayout(
        
        sidebarPanel(
          checkboxGroupInput(
            "images",
            "Select images",
            choiceNames = c("Stackoverflow", "Stackexchange", "Asymptote"),
            choiceValues = c(
              "https://upload.wikimedia.org/wikipedia/fr/9/95/Stack_Overflow_website_logo.png",
              "https://upload.wikimedia.org/wikipedia/commons/6/6f/Stack_Exchange_Logo.png",
              "https://www.clipartmax.com/png/small/203-2038151_asymptote-vector-graphics-language-wikipedia-rh-en-asymptote.png"
            )
          )
        ),
        
        mainPanel(
          tags$div(
            class = "content",
            uiOutput("carousel-ui"),
          )
        )
      )
    )
    
    server <- function(input, output) {
      
      output[["carousel-ui"]] <- renderUI({
        imgs <- lapply(input[["images"]], function(x){
          tags$img(src = x, width = "50vw")
        })
        imgs_div <- do.call(function(...) div(id = "carousel", ...), imgs)
        script <- tags$script(HTML(
        "$('#carousel').slick({
          arrows: true,
          dots:true
        });"))
        do.call(tagList, list(imgs_div, script))
      })
      
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)
    

    enter image description here