I am just learning R Shiny and have been playing around with the various examples in the gallery. For the "Image Output" example:
http://shiny.rstudio.com/gallery/image-output.html
I was wondering how I might be able to include an image headline when I select either the chainring or smiley radio button. For example after selecting "smiley" I would like the title "Smiley" to display below the image. Thank you for your help. Below is the code that is also included in the link above. (Some of it was intentionally deleted for clarity). Thank you
library(png) # For writePNG function
shinyServer(function(input, output, session) {
# A temp file to save the output.
# This file will be automatically removed later by
# renderImage, because of the deleteFile=TRUE argument.
outfile <- tempfile(fileext = ".png")
# Generate the image and write it to file
x <- matrix(rep((0:(width-1))/(width-1), height), height,
byrow = TRUE)
y <- matrix(rep((0:(height-1))/(height-1), width), height)
pic <- gauss2d(x, y, input$r)
writePNG(pic, target = outfile)
# Return a list containing information about the image
list(src = outfile,
contentType = "image/png",
width = width,
height = height,
alt = "This is alternate text")
}, deleteFile = TRUE)
# image2 sends pre-rendered images
output$image2 <- renderImage({
if (is.null(input$picture))
return(NULL)
if (input$picture == "face") {
return(list(
src = "images/face.png",
contentType = "image/png",
alt = "Face"
))
} else if (input$picture == "chainring") {
return(list(
src = "images/chainring.jpg",
filetype = "image/jpeg",
alt = "This is a chainring"
))
}
}, deleteFile = FALSE)
})
shinyUI(fluidPage(
titlePanel("Client data and query string example"),
fluidRow(
column(4, wellPanel(
sliderInput("r", "Radius :", min = 0.05, max = 1,
value = 0.2, step = 0.05),
radioButtons("picture", "Picture:",
c("chainring", "face"))
)),
column(4,
imageOutput("image1", height = 300),
imageOutput("image2")
)
)
Does this help?
ui.R
library(shiny)
shinyUI(fluidPage(
titlePanel("Image title"),
sidebarLayout(
sidebarPanel(
sliderInput("obs", "Number of observations:",
min = 0, max = 1000, value = 500)
),
mainPanel(
imageOutput("myImage"),
uiOutput("text")
)
)
))
server.R
library(shiny)
shinyServer(function(input, output) {
output$myImage <- renderImage({
outfile <- tempfile(fileext='.png')
png(outfile, width=400, height=300)
hist(rnorm(input$obs), main = "")
dev.off()
list(src = outfile,
contentType = 'image/png',
width = 400,
height = 300,
alt = "This is alternate text")
}, deleteFile = TRUE)
histogramTitle <- reactive({
paste("<h5>", input$obs, " observation used to create the histogram</h5>", sep = "")
})
output$text <- renderUI({
HTML(as.character(histogramTitle()))
})
})
Related
I have a shiny app to load pictures and I should be able to select some of the images by clicking on them and the selected images will be recorded.
I want a function that I can select and mark pictures the same way you mark photos in the gallery of a phone.
Currently, I made an app that the selected images are replaced by an empty icon. Here is what I have tried:
ui <-fluidPage(column(
width=9,
align="center",
imageOutput(outputId = "img1", click = clickOpts(id = "img1_click", clip = FALSE),width = 150,height = 150,inline = TRUE)
,imageOutput(outputId = "img2", click = clickOpts(id = "img2_click", clip = FALSE),width = 150,height = 150,inline = TRUE)
))
server <- function(input, output, session) {
empty_img="/empty.jpeg"
vals=reactiveValues(img=list.files("/images/"))
vals2=reactiveValues(img=list.files("/images/"))
empty_img_to_normal_value=reactiveValues(m=1:length(vals$img))
output$img1 <- renderImage({
list(src = vals$img[1], width = "200", height = "200") } ,deleteFile = FALSE)
observeEvent(input$img1_click, {
if(empty_img_to_normal_value$m[1]==1){
vals$img[1]=empty_img
empty_img_to_normal_value$m[1]=0
}else{
vals$img[1]=vals2$img[1]
empty_img_to_normal_value$m[1]=1
}
})
output$img2 <- renderImage({
list(src = vals$img[2], width = "200", height = "200")} ,deleteFile = FALSE)
observeEvent(input$img2_click, {
if(empty_img_to_normal_value$m[2]==1){
vals$img[2]=empty_img
empty_img_to_normal_value$m[2]=0
}else{
vals$img[2]=vals2$img[2]
empty_img_to_normal_value$m[2]=1
}
})
}
Following our comments, I made a proper answer.
# list of images URLs, replace them with your images
lst_urls <- list("data/Rplot1.png", "data/Rplot1.png", "data/Rplot1.png", "data/Rplot1.png",
"data/Rplot5.png","data/Rplot5.png","data/Rplot5.png","data/Rplot5.png")
img_w <- "100%"
img_h <- 200
mod_img_UI <- function(id) {
ns <- NS(id)
tagList(
tags$style(".checkbox{margin-bottom: -40px;}"),
column(
width =2,
checkboxInput(
inputId = ns("select_img"), label = NULL
),
imageOutput(
outputId = ns("img"), width = img_w, height = img_h, inline = TRUE
)
)
)
}
mod_img_SERVER <- function(input, output, session, img_url){
ns <- session$ns
output$img <- renderImage({
list(src = img_url,
alt = "This is alternate text",
width = img_w,
height = img_h,
contentType = "image/png")
}, deleteFile = FALSE)
return(input$select_img)
}
ui <- fluidPage(
uiOutput("images")
)
server <- function(input, output, session) {
output$images <- renderUI({
lapply(
1:length(lst_urls),
function(i) {
mod_img_UI(id = paste0("img", i))
}
)
})
observe({
selected_imgs <- lapply(
1:length(lst_urls),
function(i) {
callModule(
module = mod_img_SERVER,
session = session,
id = paste0("img", i),
img_url = lst_urls[[i]]
)
}
)
print(paste("You picked :",lst_urls[unlist(selected_imgs)]))
})
}
shinyApp(ui, server)
I'm trying to get input from the User( a bunch of images) and then display them on R shiny using Lightbox gallery. Unfortunately I'm unable to get the images, Please help with this regard,Thank you in advance for your help .
below is my code:
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
fileInput(inputId = "file_upload", label = "Upload Images", multiple = TRUE, accept = c('image/*', ".zip"),
width = NULL, buttonLabel = "Browse",
placeholder = "No file selected"),
actionButton("go","Run")
)
),
mainPanel(
fluidRow(
column(12,(uiOutput('lb'))
))
)
)
)
server <- function(input, output) {
vals<-reactiveValues(result=NULL,img_fldr_name=NULL,images=NULL)
observeEvent(input$file_upload, {
c_t <- Sys.time()
dt_str <- format(c_t, "%Y_%m_%d")
hr_str <- format(c_t, "%H_%M_%S")
vals$img_fldr_name <- paste0(dt_str, "_", hr_str)
if (tools::file_ext(input$file_upload$datapath)[[1]] %in% c("jpeg","png","jpg")){
create_folder_name=paste0("trials/www/",vals$img_fldr_name)
dir.create(path = create_folder_name)
for(i in 1:length(input$file_upload$datapath)){
file.copy(input$file_upload$datapath[[i]], paste0(create_folder_name,"/",input$file_upload$name[[i]]), overwrite = TRUE)
}
df <- list.files(paste0("trials/www/",vals$img_fldr_name), full.names = T)
print(df)
images<<-data.frame(src=list.files(paste0("trials/www/",vals$img_fldr_name), full.names = T))
#print(head(vals$images))
vals$result<-images
}
})
observeEvent(input$go,{
output$lb <- renderUI({
images <<- data.frame(src = vals$result$src)
vals$images <- images
lightbox_gallery <- function(df, gallery, display = 'block'){
print(df)
tags$div(style = sprintf('display: %s;', display),
tagList(tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "lightbox-2.10.0/lightbox.min.css"),
tags$link(rel = "stylesheet", type = "text/css", href = "gallerystyle.css")
),
tags$div(class = 'card-deck',
lapply(seq_len(nrow(df)), function(i){
print("Inside Loop")
print(df$src[i])
tags$div(`data-type`="template", class = 'card',
tags$a(#id = df$key[i],
href = df$src[i],
`data-lightbox` = gallery, # this identifies gallery group
`data-title` = paste0("Image"),
tags$span(style="color:black;text-align: center"),
tags$img(class = 'card-img-top',
src = df$src[i],
width = '80px',
height = 'auto')),
)
})
),
includeScript("www/lightbox-2.10.0/lightbox.min.js")
))
}
lightbox_gallery(vals$images, 'gallery', display = TRUE)
#paste0()
})
})
}
shinyApp(ui = ui, server = server)
Print statement inside loop gives proper path to image.
Also the respective folders and scripts are in place.
The code below works. I removed the nesting of how you prepare the output for better readability.
I think the main problem was that you read the image files from a directory outside www in your project folder. I would keep everything in there. This makes it easier. Take a look at the code: when the images are uploaded I explicitely save them to www/.... While preparing the output, I remove the www prefix using gsub, since Shiny is looking for resources in there by default.
Finally, make sure to use reactive values properly. You don't need to define a global images variable. Just use the reactive values. And there again, it is probably sufficient to have one reactive value which holds all the paths as a vector (e.g. paths <- reactiveVal(NULL)).
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fluidRow(
fileInput(inputId = "file_upload", label = "Upload Images", multiple = TRUE, accept = c('image/*', ".zip"),
width = NULL, buttonLabel = "Browse",
placeholder = "No file selected"),
actionButton("go","Run")
)
),
mainPanel(
fluidRow(
column(12,(htmlOutput('lb'))
))
)
)
)
server <- function(input, output) {
vals<-reactiveValues(result=NULL,img_fldr_name=NULL,images=NULL)
observeEvent(input$file_upload, {
c_t <- Sys.time()
dt_str <- format(c_t, "%Y_%m_%d")
hr_str <- format(c_t, "%H_%M_%S")
vals$img_fldr_name <- paste0(dt_str, "_", hr_str)
if (tools::file_ext(input$file_upload$datapath)[[1]] %in% c("jpeg","png","jpg")){
create_folder_name=paste0("www/trials/www/",vals$img_fldr_name)
dir.create(path = create_folder_name)
for(i in 1:length(input$file_upload$datapath)){
file.copy(input$file_upload$datapath[[i]], paste0(create_folder_name,"/",input$file_upload$name[[i]]), overwrite = TRUE)
}
images <- data.frame(src=list.files(paste0("www/trials/www/",vals$img_fldr_name), full.names = T))
vals$result <- images
}
})
get_lb <- eventReactive(input$go,{
images <- data.frame(src = vals$result$src)
vals$images <- images
lightbox_gallery(vals$images, 'gallery', display = TRUE)
})
lightbox_gallery <- function(df, gallery, display = 'block'){
tags$div(style = sprintf('display: %s;', display),
tagList(tags$head(
tags$link(rel = "stylesheet", type = "text/css", href = "lightbox.min.css"),
tags$link(rel = "stylesheet", type = "text/css", href = "gallerystyle.css")
),
tags$div(class = 'card-deck',
lapply(seq_len(nrow(df)), function(i){
print("Inside Loop")
print(df$src[i])
tags$div(`data-type`="template", class = 'card',
tags$a(#id = df$key[i],
href = gsub("^www/", "", df$src[i]),
`data-lightbox` = gallery, # this identifies gallery group
`data-title` = paste0("Image"),
tags$span(style="color:black;text-align: center"),
tags$img(class = 'card-img-top',
src = df$src[i],
width = '80px',
height = 'auto')),
)
})
),
includeScript("www/lightbox.min.js")
))
}
output$lb <- renderUI({
get_lb()
})
}
shinyApp(ui = ui, server = server)
is there any way in R, shinydashboard, to render multiple images in the dashboard body based on the selectinput option?
Here are my codes:
library(shiny)
library(shinydashboard)
images_a <- list.files("input/plots 1/", pattern = ".png") # 6 'png' images are in the *input/plots 1* folder
images_b <- list.files("input/plots 1/", pattern = ".jpg") # 5 'jpg' images are in the *input/plots 1* folder
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(selectInput(inputId = "image_type", label = "Image type", choices = c("png", "jpg"), selected = "png")),
dashboardBody()
)
server <- function(input, output) {
}
shinyApp(ui, server)
Thank you!
Use lapply( ) to loop through in renderImage( )
download.file("http://dehayf5mhw1h7.cloudfront.net/wp-content/uploads/sites/38/2016/01/18220900/Getty_011816_Bluepenguin.jpg",
destfile = "Bowie.png")
download.file("http://3.bp.blogspot.com/_cBH6cWZr1IU/TUURNp7LADI/AAAAAAAABsY/76UhGhmxjzY/s640/penguin+cookies_0018.jpg",
destfile = "Cookie.png")
function(input, output) {
output$img1 <- renderImage({ #This is where the image is set
if(input$var == "Bowie"){
list(src = "Bowie.png", height = 240, width = 300)
}
else if(input$var == "Cookie"){
list(src = "Cookie.png", height = 240, width = 300)
}
else if(input$var == "Renesme"){
list(src = "Renesme.png", height = 240, width = 300)
}
else if(input$var == "Mango"){
list(src = "Mango.png", height = 240, width = 300)
}
})
I'm trying to shift elements out of the way for rendered images not to overlap with anything (trying to do it dynamically so that any size page fits and just pushed everything out of the way sort of)... Pretty new to this whole thing. Thank you in advance!
library(shiny)
library(webshot)
ui <- fluidPage(
titlePanel(
fluidRow ( align = "center", h3("Screens"))
),
sidebarLayout(
#Side panel lay out to include variant, gene and disease info relevant to interpretation
sidebarPanel(width=3,
h5("Screens")),
mainPanel(
textInput("screen1", h5("Screenshot1"),
value = "http://example.com/", width = "100%", placeholder = NULL),
imageOutput("screen1"),
textInput("screen2", h5("Screenshot2"),
value = "http://example.com/", width = "100%", placeholder = NULL),
imageOutput("screen2")
)))
server <- function(input, output, session) {
output$screen1 <- renderImage({
webshot(input$screen1, zoom = 1,
file = "screen1.png")
list(src = "screen1.png",
contentType = 'image/png')
})
output$screen2 <- renderImage({
webshot(input$screen2 , zoom = 1,
file = "screen2.png")
list(src = "screen2.png",
contentType = 'image/png')
})
}
shinyApp(ui = ui, server = server)
I'm trying to display images in my shiny app reactively. I've successfully done that in the server.R script with:
output$display.image <- renderImage({
image_file <- paste("www/",input$image.type,".jpeg",sep="")
return(list(
src = image_file,
filetype = "image/jpeg",
height = 520,
width = 696
))
}, deleteFile = FALSE)
BUT it's very slow.
However, it is VERY fast to embed one of the images into the ui.R script like so:
tabPanel("Live Images", img(src = "img_type1.jpeg"))
Why is there such a difference? Is there any way to make the reactive images appear faster?
Hi you can use conditionalPanel to do this, it embed all your images but only the one which have TRUE to the condition will be displayed :
tabPanel("Live Images",
conditionalPanel(condition = "input.image_type == 'img_type1'",
img(src = "img_type1.jpeg")
),
conditionalPanel(condition = "input.image_type == 'img_type2'",
img(src = "img_type2.jpeg")
)
)
And change the name of your input from image.type to image_type because . have special meaning in Javascript (as between input and image_type).
If you have a lot of images, you can always do something like that :
tabPanel("Live Images",
lapply(X = seq_len(10), FUN = function(i) {
conditionalPanel(condition = paste0("input.image_type == 'img_type", i, "'"),
img(src = paste0("img_type", i, ".jpeg"))
)
})
)
For example, with images from this post by tsperry (you can find it on rbloggers too), you can do :
library("shiny")
ui <- fluidPage(
tabsetPanel(
tabPanel("Live Images",
# 50 images to display
lapply(X = seq_len(50), FUN = function(i) {
# condition on the slider value
conditionalPanel(condition = paste0("input.slider == ", i),
# images are on github
img(src = paste0("https://raw.githubusercontent.com/pvictor/images/master/",
sprintf("%04d", i), "plot.png"))
)
}),
sliderInput(inputId = "slider", label = "Value", min = 1, max = 50, value = 1,
animate = animationOptions(interval = 100, loop = TRUE))
)
)
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)