2016-05-04 8 views
7

Sto costruendo un'app lucida in cui gli utenti fanno clic su un'immagine e questo li fa avanzare a un'altra immagine. Questo sembra relativamente semplice, ma prima che l'utente veda la prima immagine, deve inserire il suo indirizzo email. Per raggiungere questo obiettivo, ho utilizzato conditionalPanel in cui la prima immagine viene visualizzata solo quando l'utente preme un pulsante di azione. Tuttavia, quando il pannello per le immagini è incorporato all'interno di conditionalPanel, l'argomento click per imageOutput sembra non funzionare più.imageOutput click within condizionalePanel

Ho una directory denominata images con 9 immagini contenute al suo interno, con nomi di file 1.png, 2.png...9.png (a proposito, se c'è un modo di caricare questa directory per rendere questo esempio più facilmente replicabile, sarei felice di prendere suggerimenti!). Il seguente MWE - che non include l'elemento conditionalPanel - funziona bene:

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) 

Tuttavia, quando includo l'elemento conditionalPanel, cliccando sull'immagine non sembra produrre una nuova immagine. Questo è il codice che sto usando:

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) 

Il problema è che, anche se il primo conditionalPanel sembra fare il suo lavoro - l'utente vede il "Inserisci il tuo indirizzo e-mail" prima, e vede solo la prima immagine dopo aver cliccato su "Vai" - facendo clic sull'immagine non si avanza più l'utente in avanti all'immagine successiva. Qualsiasi idea sarebbe più apprezzata.

risposta

3

A scopo di verifica ho generato 9 file PNG con i numeri da 1 a 9 utilizzando il seguente codice

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() 
} 

Ho anche fatto alcuni cambiamenti nel codice:

  • pannelli Invece condizionali c'è un'interfaccia utente dinamica che dipende da value$i

  • Inizialmente value$i è impostato su -1 un d textInput e un pulsante sono mostrati

  • Se l'utente immette una stringa di caratteri che contiene @ e preme il pulsante, il valore di value$i viene incrementato di 1 e il plotOutput è mostrato.

  • Se la stringa di caratteri inputed non contiene @ viene mostrato un messaggio di avviso (shinyBS)


Il problema è in qualche modo causato dal ridimensionamento plotOutput utilizzando parametri height e width. Il input$photo_click non restituisce quindi un valore o più precisamente restituisce NULL. Se la trama non viene ridimensionata, tutto funziona perfettamente. Quindi una delle soluzioni è inserire plotOutput all'interno di div e utilizzare molto semplice CSS per impostare la dimensione desiderata dell'output.

è possibile ridimensionare il div come segue:

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

Si può giocare con i valori di height e width all'interno di un div e con la dimensione dei file PNG per ottenere un risultato desiderato.

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

Il colore di sfondo è impostato su rosso e i file PNG sono grigi per facilitare il posizionamento.

Spero che questa soluzione sarà utile a voi:


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) 
+0

Grande risposta. Grazie per essere così completo. – user2728808