I've been successful at using renderImage() function to output one image file to the UI, but I was wondering if there was any way to draw a dynamic amount of photos and stack them all on top of each other in the UI main panel. The background algorithm of my app generates a folder of output images, and I was wondering if anyone knew of a way to loop through that folder and stack the images in the UI. I'm not sure how many images will be produced since it depends on the input and is generated reactively when the input is submitted.
This seems to work. I've modified the stock shiny app and used shinyFiles to select the image files into paths which you can replace with path names to your images using your favourite approach.
library(shiny)
library(shinyFiles)
library(purrr)
ui <- fluidPage(
titlePanel("My Images"),
sidebarLayout(
# Choose the images
sidebarPanel(
shinyFilesButton(
'files'
, label='File select'
, title='Please select a file'
, multiple=TRUE
)
),
# Show the images
mainPanel(
uiOutput('images')
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output, session) {
shinyFileChoose(
input,
'files',
roots = getVolumes(),
session = session,
restrictions = system.file(package = 'base')
)
output$images <- renderUI({
files <- input$files
has_root <- "root" %in% names(files)
validate(need(has_root, "Choose files"))
root <- files$root
root <- "C:" # root returns an unusable value that causes errors
paths <- files[[1]] %>% map_chr(~file.path(root, .x[[2]], .x[[3]]))
paths %>% map(
function(path){
renderImage(
list(
src = path
, alt = "Can't show file!"
, width = 500
, height = 300
)
, deleteFile = FALSE)
}
)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Welcome to the community @Couth! In addition to the previous responses, here is another way to stack a selected number of images in a shiny UI.
Within the folder where the shiny app .R file is located, I saved 10 identical images (Posit logo) within a folder named www. The code below first gathers the image filepaths via list.files, specifying the www folder. Then, within a renderUI call in the server, if the number selected is greater than 0, an HTML text statement is generated for the number of images selected. The images are stacked by including a break tag (<br>) at the end of the HTML statement.
library(shiny)
# get filepaths for all images in the wwww folder
my_images = list.files('www', full.names = F, pattern = '.PNG')
ui <- fluidPage(
br(),
selectInput('number',
'Select the number of images to show',
choices = 0:length(my_images),
multiple = F
),
br(),
uiOutput('images')
)
server <- function(input, output, session) {
output$images = renderUI({
req(input$number)
# show image(s) if 1 or more is selected
if(input$number > 0) {
display_image = function(i) {
HTML(paste0('<img src = ', my_images[i], ' style="margin-top: 5px;"><br>'))
}
lapply(1:input$number, display_image)
}
})
}
shinyApp(ui, server)