r shiny - 使用 imageOutput() 和 renderImage() 绘制多个图像

r shiny - Plotting multiple images using the imageOutput() and renderImage()

我正在尝试绘制保存在我闪亮的应用程序文件夹的 www 子目录文件夹中的几张图像。图像文件名在数据框列中;假设“img_path”。

我在服务器界面中使用 UI 和 renderImage() 中的 imageOutput() 函数。 由于我想绘制 www 子文件夹中以及数据框中引用的所有图像,因此我使用了 for 循环。

不幸的是,它不会渲染所有图像,而是始终显示最后一张图像。我猜这是因为图像相互叠加。

假设我有:我的数据

df_img <- data.frame(id = c(1:5), img_path = c("h1000.png", "h2000.png", "h3000.png", "h4000.png", "h000.png"))

存放在data子文件夹中; www 子文件夹中的 5 张图像的命名与 df_img[["img_path"]] 中的相同。 我的基本闪亮应用程序代码是:

library(shiny)
library(shinydashboard)

定义UI

ui <- fluidPage(
    # Application title
    titlePanel("Test app"),
    # to render images in the www folder 
    box(imageOutput("houz"), width = 3)
)

定义服务器逻辑

server <- function(input, output) {
    df_img <- read.csv("data/df_img.csv", header = T)
    for (i in 1:nrow(df_img)) {
        output$houz <- renderImage({
            list(
                src = file.path('www', df_img$img_path[i]),
                contentType = "image/jpeg",
                width = "100%", height = "45%"
            )
        }, deleteFile = FALSE)
        
    }
}

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

what_i_expect and what_i_get

考虑使用 Shiny 模块。下面是一个工作示例,假设您在工作目录的“www”子目录中有扩展名为“jpeg”的图像。我使用 purrr 进行函数式编程 - 如果您愿意,可以使用 lapply()for 循环。

Chapter 19 of Mastering Shiny 是对闪亮模块的一个很好的介绍。

library(shiny)
library(purrr)

ui_module <- function(id) {
  imageOutput(NS(id, "img"))
}

server_module <- function(id,
                          img_path) {
  moduleServer(
    id,
    function(input, output, session) {
  output$img <- renderImage({
    list(src = img_path,
         contentType = "image/jpeg",
         width = "100%",
         height = "45%")
  },
  deleteFile = FALSE)
    })
}

images <- list.files(path = "www",
                     pattern = "jpeg",
                     full.names = TRUE)

ids <- tools::file_path_sans_ext(
  basename(images)
)

ui <- fluidPage(
  map(ids, ui_module)
  )

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

  map2(.x = ids,
       .y = images,
       .f = server_module)

}

shinyApp(ui, server)

您可以使用renderUI来显示您想要显示的图像列表。试试这个

df_img <- data.frame(id = c(1:5), img_path = c("h1000.png", "h2000.png", "h3000.png", "h4000.png", "h000.png"))

ui <- fluidPage(
  # Application title
  titlePanel("Test app"),
  # to render images in the www folder 
  box(uiOutput("houz"), width = 3)
)

server <- function(input, output) {
  #df_img <- read.csv("data/df_img.csv", header = T)
  
  n <- nrow(df_img)
  
  observe({
    for (i in 1:n)
    {
      print(i)
      local({
        my_i <- i
        imagename = paste0("img", my_i)
        print(imagename)
        output[[imagename]] <-
          renderImage({
            list(src = file.path('www', df_img$img_path[my_i]), 
                 width = "100%", height = "55%",
                 alt = "Image failed to render")
          }, deleteFile = FALSE)
      })
    }
  })
  
  
  output$houz <- renderUI({
    
    image_output_list <- 
      lapply(1:n,
             function(i)
             {
               imagename = paste0("img", i)
               imageOutput(imagename)
             })
    
    do.call(tagList, image_output_list)
  })
  
}

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