【问题标题】:imageOutput click within conditionalPanelimageOutput 在条件面板内点击
【发布时间】:2016-05-04 16:30:06
【问题描述】:

我正在构建一个闪亮的应用程序,用户在该应用程序中单击一个图像,这会将他们推进到另一个图像。这看起来相对简单,但在用户查看第一张图片之前,他们需要输入他们的电子邮件地址。为了实现这一点,我一直在使用conditionalPanel,其中只有在用户点击操作按钮时才会显示第一张图片。但是,当图像面板嵌入到 conditionalPanel 中时,imageOutputclick 参数似乎停止工作。

我有一个名为 images 的目录,其中包含 9 张图像,文件名为 1.png, 2.png...9.png(顺便说一句,如果有办法上传此目录以使此示例更易于复制,我会乐于接受建议!)。以下 MWE(不包括 conditionalPanel 元素)运行良好:

library(shiny)

## User interface
ui <- fluidPage(
  h1("MWE",align="center"),
  fluidRow(
    column(4, conditionalPanel(condition = "input.signingo == 0", 
                               wellPanel(
                             textInput("who",label = "Please enter your email address.", value=""),
                             actionButton("signingo",label="Go.")
                           ))
),

column(6, align="center",
                        wellPanel(
                          imageOutput("image", height = 175, width = 116, click = "photo_click")
                        )
)
  )

) 

server <- function(input, output){

  values <- reactiveValues(i = 0, selections = sample(1:9,1))

  ## Load image
  output$image <- renderImage({
filename <- normalizePath(file.path(paste0('images/',values$selections,".png")))

# Return a list containing the filename and alt text
list(src = filename,
     alt = paste(input$name))

  }, deleteFile = FALSE)

## Function to increment counter by one and to randomly select new image
  click.function <- function(){isolate({
    values$i <- values$i + 1
values$selections <- sample(1:9,1)
  })}

  ## Move on
  observeEvent(input$photo_click,{click.function() })

}
shinyApp(ui = ui, server = server)

但是,当我包含 conditionalPanel 元素时,单击图像似乎不再生成新图像。这是我正在使用的代码:

  library(shiny)

  ## User interface
  ui <- fluidPage(
h1("MWE",align="center"),
fluidRow(
  column(4, conditionalPanel(condition = "input.signingo == 0", 
                             wellPanel(
                               textInput("who",label = "Please enter your email address.", value=""),
                               actionButton("signingo",label="Go.")
                             ))
  ),

  column(6, align="center",
         conditionalPanel(condition = "input.signingo > 0", 
                          wellPanel(
                            imageOutput("image", height = 175, width = 116, click = "photo_click")
                          ))
  )
)
)

  server <- function(input, output){

values <- reactiveValues(i = 0, selections = sample(1:9,1))

## Load image
output$image <- renderImage({
  filename <- normalizePath(file.path(paste0('images/',values$selections,".png")))

  # Return a list containing the filename and alt text
  list(src = filename,
       alt = paste(input$name))

}, deleteFile = FALSE)

## Function to increment counter by one and to randomly select new image
click.function <- function(){isolate({
  values$i <- values$i + 1
  values$selections <- sample(1:9,1)
})}

## Move on
observeEvent(input$photo_click,{click.function() })
}
shinyApp(ui = ui, server = server)

问题是,虽然第一个conditionalPanel 似乎在做它的工作——用户首先看到“请输入您的电子邮件地址”,然后在点击“开始”后才看到第一张图片——点击image 不再使用户前进到下一个图像。任何想法将不胜感激。

【问题讨论】:

    标签: r shiny


    【解决方案1】:

    出于测试目的,我使用以下代码生成了 9 个数字从 1 到 9 的 png 文件

    for (i in 1:9) {
      #png(paste0(i, ".png"), bg = "grey") # you can manipulate the size of graphics 
      png(paste0(i, ".png"), bg = "grey", height = 400, width = 400) 
      plot(1:10, type = "n", axes = F, xlab = "", ylab = "")
      text(5,5, i, cex = 15, col = i)
      box()
      dev.off()
    }
    

    我还对您的代码做了一些更改:

    • 有一个动态 UI 取而代之的是条件面板,它依赖于 value$i

    • 最初将value$i 设置为-1textInput,并显示一个按钮

    • 如果用户输入包含@ 的字符串并按下按钮,则value$i 的值加1,并显示plotOutput。

    • 如果输入的字符串不包含@,则会显示警告(shinyBS


    问题是由使用参数heightwidth 调整plotOutput 的大小引起的。然后input$photo_click 不返回值或更准确地说它返回NULL。如果情节没有调整大小,一切都完美无缺。所以解决方案之一是将plotOutput 放在div 中,并使用非常简单的CSS 来设置所需的输出大小。

    您可以按如下方式调整 div 的大小:

    div(style = "background:red; height: 400; width: 400;", 
                imageOutput("image", click = "photo_click")
              )
    

    您可以在 div 中使用 heightwidth 的值以及使用 png 文件的大小来获得所需的结果。

     ... 
     png(paste0(i, ".png"), bg = "grey", height = 400, width = 400) 
     ...
    

    背景色设置为红色,png文件设置为灰色,方便定位。

    希望这个解决方案对你有所帮助:


    library(shiny)
    library(shinyBS)
    
    ## User interface
    ui <- fluidPage(
      uiOutput("dynamic")
    )
    
    server <- function(input, output, session){
    
    
      output$dynamic <- renderUI({
        if (values$i == -1) { 
          list(
            h1("MWE", align = "center"),
            wellPanel(
               textInput("who", label = "Please enter your email address.", value = ""),
               actionButton("signingo", label = "Go."),
               bsAlert("alert")
            )
          )
        }
        else {
          fluidRow(
            column(4),
            column(6,
              # imageOutput("image", height = 175, width = 116, click = "photo_click")
              # Setting a custom height and width causes the problem.
    
              # You can wrap imageOutput into a div. 
              div(style = "background:red; height: 400; width: 400;", 
                imageOutput("image", click = "photo_click")
              )
            )
          )
        }
      })
    
      # values$i changed to -1
      values <- reactiveValues(i = -1, selections = sample(1:9,1))
    
      ## Load image
      output$image <- renderImage({
        filename <- normalizePath(file.path(paste0('images/',values$selections,".png")))
        #filename <- paste0("/Users/User/Downloads/images/", values$selections, ".png")
    
        # Return a list containing the filename and alt text
        # list(src = filename,
        #      alt = paste(input$name)) # I don't know what is input$name
    
        list(src = filename,
             alt = paste(values$i))
    
      }, deleteFile = FALSE)
    
      ## Function to increment counter by one and to randomly select new image
      click.function <- function(){ # isolate({
        values$i <- values$i + 1
        values$selections <- sample(1:9,1)
      # })
    }
    
      # increment once values$i (from -1 to 0) to close the first menu.
      observeEvent(input$signingo, {
        #if (input$who != "") 
        # Require that the inputed string includes @
        if (gregexpr(pattern = "@", input$who) != -1) { 
          click.function()
          closeAlert(session, "Alert")
    
        } else {
          # If the inputed string doesen't contain @ create a warning
          createAlert(session, "alert", "Alert", title = "Not valid email",
                      content = "", dismiss = T, style = "warning")
        }
      })
    
      observeEvent(input$photo_click, {
        click.function() 
      })
    }
    shinyApp(ui = ui, server = server)
    

    【讨论】:

    • 很好的答案。谢谢你这么彻底。
    猜你喜欢
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-03
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    相关资源
    最近更新 更多