提问人:Limey 提问时间:2/3/2021 更新时间:2/3/2021 访问量:396
在同一UI元素中按顺序整齐地显示不同大小的图像
Neatly display images of different sizes sequentially in the same UI element
问:
在我的应用中,我需要在其他 UI 元素中显示单个预渲染图像。我希望其他元素紧紧地包裹在图像的顶部和底部。显示的图像取决于应用的状态,并且图像的大小可能不同。
这个问题解决了一个类似的问题,但似乎不同之处在于需要同时显示许多不同大小的图像。
这是显示问题的 MWE。您可以提供自己的图像,也可以在此处将它们与我的 RStudio 项目的其余部分一起下载。
library(shiny)
library(png)
ui <- fluidPage(
tags$head(tags$link(rel="stylesheet", type="text/css", href="stylesheet.css")),
selectInput("size", label="Size:", choices=c("small", "large")),
imageOutput("image"),
# uiOutput("imageUI"),
textOutput("info")
)
# Define server logic required to draw a histogram
server <- function(input, output) {
imgFileName <- reactive({
paste0("./www/", input$size, ".png")
})
imgFile <- reactive({
readPNG(imgFileName(), info=TRUE)
})
imgSize <- reactive({
info <- unlist(stringr::str_split(attr(imgFile(), "info")$dim, stringr::fixed(" ")))
info <- paste0(info, "px")
names(info) <- c("width", "height")
info <- as.list(info)
info
})
output$info <- renderText({
paste0("Height: ", imgSize()$height, "; Width: ", imgSize()$width)
})
output$image <- renderImage({
list(
src=imgFileName(),
contentType="image/png",
width=imgSize()$width,
height=imgSize()$height,
alt=paste0("A ", input$size, " image"),
class="myImageClass"
)
})
# output$imageUI <- renderUI({
# tagList(plotOutput("image"))
# })
}
shinyApp(ui, server)
如果运行 MWE,您将看到,当选择输入的值为 时,图像和文本输出之间存在较大的间隙,而当选择输入为 时,图像与文本输出重叠。small
large
这些屏幕截图显示所需的行为。
检查底层 HTML(在 Firefox 中,右键单击图像上的任意位置并选择“检查元素”),问题似乎是由包装图像的 引起的:div
已正确拾取图像的大小,但周围的元素被周围的 inline 属性固定在适当的位置。为了证明这是问题所在,我可以在 Firefox 的检查器中禁用有问题的高度属性:img
height
div
这给了我想要的行为。
如果问题是由 中引用的 CSS 类之一引起的,我可能可以通过覆盖应用程序样式表中的类定义来解决问题。但是有问题的属性是内联的,所以这不是一个选项。div
如何修改包装显示图像的属性?div
img
答:
1赞
the-mad-statter
2/3/2021
#1
你非常接近这是必要的,因为你希望UI的布局改变。而您取消注释的内容只会将图像换入和换出,但会保持 UI 布局不变。uiOutput()
library(shiny)
library(png)
ui <- fluidPage(
tags$head(tags$link(rel="stylesheet", type="text/css", href="stylesheet.css")),
selectInput("size", label="Size:", choices=c("small", "large")),
# don't use imageOutput() here because the UI will not be able to change
#imageOutput("image"),
# instead use uiOutput() which will allow you to update the UI itself
# that is, you will be able to update the height of the image div reactively
uiOutput("imageUI"),
textOutput("info")
)
server <- function(input, output) {
imgFileName <- reactive({
paste0("./www/", input$size, ".png")
})
imgFile <- reactive({
readPNG(imgFileName(), info=TRUE)
})
imgSize <- reactive({
info <- unlist(stringr::str_split(attr(imgFile(), "info")$dim, stringr::fixed(" ")))
info <- paste0(info, "px")
names(info) <- c("width", "height")
info <- as.list(info)
info
})
output$info <- renderText({
paste0("Height: ", imgSize()$height, "; Width: ", imgSize()$width)
})
output$image <- renderImage({
list(
src=imgFileName(),
contentType="image/png",
width=imgSize()$width,
height=imgSize()$height,
alt=paste0("A ", input$size, " image"),
class="myImageClass"
)
})
# update the UI here by changing the height of the image div
output$imageUI <- renderUI({
imageOutput("image", height = imgSize()$height)
})
}
shinyApp(ui, server)
评论
0赞
Limey
2/3/2021
真棒。谢谢。正如你所推测的那样,我尝试了各种方法,但解决方案显然是我错过的。这正是我想要的。renderUI
评论