【问题标题】:R Shiny data table images not updating when running in browserR Shiny 数据表图像在浏览器中运行时未更新
【发布时间】:2019-06-11 13:40:48
【问题描述】:

我正在创建一个闪亮的应用程序,它在数据表中显示图像和文本。该表将需要根据用户的输入进行更新。当我在窗口中运行应用程序时,表格会按预期更新。但是,当我在浏览器中运行它时,文本会更新,但图像不会。如何让它在浏览器中运行?

编辑:为清楚起见,以下示例只是为了重现该问题。真正的应用程序可以显示任意数量的不同图片,这些图片在用户做出选择之前不会保存在本地(它们是从数据库中提取的)。我希望避免使用不同的文件名,因为我可能最终会在本地保存数十万张图片,但如果这是唯一的解决方案,那么我将不得不定期清理文件夹

可重现的示例(需要 2 个本地图像)

library(shiny)
library(imager)
library(DT)

# Define UI
ui <- fluidPage(

  # Application title
  titlePanel("Tables to export"),

  sidebarLayout(
    sidebarPanel(
      actionButton("pic1","Pic1"),
      actionButton("pic2","Pic2")
    ),

    # Show tables
    mainPanel(
      fluidRow(
        dataTableOutput('tab1')
      )
    )
  )
)

# Define server logic 
server <- function(input, output) {

  observeEvent(input$pic1, {
    pic <- load.image("www/pic1.png")
    save.image(pic,"www/picToShow.png")

    tab1 <- datatable(t(data.frame("Pic"='<img src="picToShow.png" width=150 height=100>',x1=1,x2=2,x3=3,row.names="p1")), 
                      escape = F, options = list(dom = 't',pageLength = 20))
    output$tab1 <- renderDataTable(tab1)
  })

  observeEvent(input$pic2, {
    pic <- load.image("www/pic2.png")
    save.image(pic,"www/picToShow.png")

    tab1 <- datatable(t(data.frame("Pic"='<img src="picToShow.png" width=150 height=100>',x1=4,x2=5,x3=6,row.names="p1")), 
                      escape = F, options = list(dom = 't',pageLength = 20))
    output$tab1 <- renderDataTable(tab1)
  })

}

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

预期行为(窗口中的行为)

浏览器中的行为

【问题讨论】:

  • 好吧,因为您将它们都写入相同的文件名“picToShow.png”,您的浏览器假定它们是同一个文件并使用缓存版本。最好不要使用相同的文件名。只需使用“pic1.png”或“pic2.png”作为图像标签中的src=。否则,您必须编写一些 javascript 来欺骗您的浏览器重新加载它认为已经加载的图像。
  • 我有一种感觉,就是这样。好的,谢谢,我看看能不能用不同的文件名。

标签: r shiny dt


【解决方案1】:

我同意@MrFlick 的评论。为什么要加载两个图像并使用相同的名称重新保存它们?浏览器会认为它已经知道该图像并将重新使用已加载的图像。

为什么不直接包含pic1.pngpic2.png

server <- function(input, output) {
  observeEvent(input$pic1, {
    tab1 <- datatable(t(data.frame("Pic"='<img src="pic1.png" width=150 height=100>',x1=1,x2=2,x3=3,row.names="p1")),
                      escape = F, options = list(dom = 't',pageLength = 20))
    output$tab1 <- renderDataTable(tab1)
  })

  observeEvent(input$pic2, {
    tab1 <- datatable(t(data.frame("Pic"='<img src="pic2.png" width=150 height=100>',x1=4,x2=5,x3=6,row.names="p1")),
                      escape = F, options = list(dom = 't',pageLength = 20))
    output$tab1 <- renderDataTable(tab1)
  })
}

【讨论】:

  • 我的实际应用程序可能有数十万张不同的图像可供选择(当用户进行选择时,图像会被下载),所以我想避免一个包含太多图像文件的文件夹现有图像被替换
  • 但是这样一来,您在服务器函数中加载和重新保存图像时浪费了有用的时间/资源。
  • 那只是为了让我的代码可重现。在用户做出选择之前,图像不存在。当他们做出选择时,会调用一个数据库并在本地保存一张图片。然后该图片显示在数据表中。如果用户做出不同的选择,则会用新图片替换它(以避免在本地保存 500,000 张图片)。
  • 啊好吧,这更有意义。比我仍然将具有唯一哈希的图像保存在某个文件夹中并将名称保存在reactiveValue 中(类似于@DSGym 的方法)。为防止该文件夹中的图像一次超过 1 张,您可以在保存新图像之前清空该目录。
【解决方案2】:
library(shiny)
library(imager)
library(DT)

# Define UI
ui <- fluidPage(

    # Application title
    titlePanel("Tables to export"),

    sidebarLayout(
        sidebarPanel(
            actionButton("pic1","Pic1"),
            actionButton("pic2","Pic2")
        ),

        # Show tables
        mainPanel(
            fluidRow(
                DT::dataTableOutput('tab1')
            )
        )
    )
)

# Define server logic 
server <- function(input, output) {

    vals = reactiveValues(pic1 = 0, pic2 = 0)

    observeEvent(input$pic1, {
        vals$pic1 <- 1
        vals$pic2 <- 0
    })

    observeEvent(input$pic2, {
        print(vals$pic1)
        print(vals$pic2)
        vals$pic1 <- 0
        vals$pic2 <- 1
    })

    dynamicdf <- reactive({

        if(vals$pic1 == 1) {
            df <- data.frame(
                pic = c('<img src="http://flaglane.com/download/american-flag/american-flag-large.png" height="52"></img>'),
                x1 = c(1),
                x2 = c(2),
                x3 = c(3)
            )
        } else {
            df <- data.frame(
                pic = c('<img src="img2.jpg" width=150 height=100></img>'),
                x1 = c(4),
                x2 = c(5),
                x3 = c(6)
            )
        }
        print(df)
        return(df)
    })

    output$tab1 <- DT::renderDataTable({
        DT::datatable(dynamicdf(), escape = FALSE)
    })

}

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

在 Shiny Apps 中,您不会加载或保存图像。您可以使用存储图片的文件夹的路径来显示它们。这可以是 Internet 上的链接或您机器上的路径。

这样做。我使用reactiveValue 来跟踪您的按钮的最后一次点击。如果您有大量可能要渲染的图片,这是一个很好的解决方案。 (我从现代 JS 库 ReactJS 中采用了这种风格)根据您显示图片的状态。 NOT 使用www 路径,这已经是闪亮的预期。将其保留在 App 中的示例 2 中。

对我来说,它也只适用于 App 中的 escape = FALSE 参数。如果没有它不起作用,请尝试。

【讨论】:

    猜你喜欢
    • 2017-07-24
    • 2012-12-03
    • 2015-12-30
    • 2018-02-21
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    相关资源
    最近更新 更多