R Shiny中Plotly仪表盘无法占满fluidRow高度,底部留白求助
解决Shiny中Plotly仪表盘在fluidRow底部留白的问题
我在R Shiny应用的fluidRow里放置了4个Plotly仪表盘(gauge),但每个图表底部始终存在难以消除的留白,超出了fluidRow的高度。已在多处设置height="100%"但问题未解决,期望仪表盘能占满fluidRow高度,且fluidRow无需固定高度,可随窗口缩放。
问题代码
main_content_MATDetail <- mainPanel( fluidRow( style = "background-color: #f0f0f0; height:200px", column(3, plotlyOutput("OAGuage", height="100%") %>% withSpinner(color = "#12436D")), column(3, plotlyOutput("UAGuage") %>% withSpinner(color = "#12436D")), column(3, plotlyOutput("AAGuage") %>% withSpinner(color = "#12436D")), column(3, plotlyOutput("PAGuage") %>% withSpinner(color = "#12436D")) ) ) ui <- fluidPage( tabsetPanel( id = "main_tabs", tabPanel("Details ", titlePanel(div("Details", style = "font-size:18px;")), main_content_MATDetail )) ) #end of fluid page server <- function(input, output, session){ count_more<-9 count_less<-17 denominator<-(count_more+count_less) prop_better <- (100 * count_less/denominator) output$OAGuage <- renderPlotly({ fig <- plot_ly( domain = list(x = c(0, 1), y = c(0, 1)), value = prop_better, title = list(text = "A"), type = "indicator", gauge = list( bar = list( color = case_when( prop_better >= 75 ~ "green", prop_better >= 50 & prop_better < 75 ~ "orange", TRUE ~ "red" ) ), axis = list(range = list(0, 100), tickvals = c(0, 25, 50, 75, 100), ticktext = c("0", "25", "50", "75", "100")) ), mode = "gauge+number" ) fig <- fig %>% layout( margin = list(l=0,r=0), paper_bgcolor = "#f0f0f0", font = list(color = "darkblue", family = "Arial")) }) output$AAGuage <- renderPlotly({ fig <- plot_ly( domain = list(x = c(0, 1), y = c(0, 1)), value = prop_better, title = list(text = "B"), type = "indicator", color="black", # plot_bgcolor = "#f0f0f0", gauge = list( # bar = list(color = "darkblue"), # bgcolor = "#f0f0f0", bar = list( color = case_when( prop_better >= 75 ~ "green", prop_better >= 50 & prop_better < 75 ~ "orange", TRUE ~ "red" ) ), axis = list(range = list(0, 100), tickvals = c(0, 25, 50, 75, 100), ticktext = c("0", "25", "50", "75", "100")) ), mode = "gauge+number" ) fig <- fig %>% layout( margin = list(l=0,r=0), height="100%", paper_bgcolor = "#f0f0f0", font = list(color = "darkblue", family = "Arial")) }) output$UAGuage <- renderPlotly({ fig <- plot_ly( domain = list(x = c(0, 1), y = c(0, 1)), value = prop_better, title = list(text = "C"), type = "indicator", color="black", # plot_bgcolor = "#f0f0f0", gauge = list( # bar = list(color = "darkblue"), # bgcolor = "#f0f0f0", bar = list( color = case_when( prop_better >= 75 ~ "green", prop_better >= 50 & prop_better < 75 ~ "orange", TRUE ~ "red" ) ), axis = list(range = list(0, 100), tickvals = c(0, 25, 50, 75, 100), ticktext = c("0", "25", "50", "75", "100")) ), mode = "gauge+number" ) fig <- fig %>% layout( margin = list(l=0,r=0), paper_bgcolor = "#f0f0f0", font = list(color = "darkblue", family = "Arial")) }) output$PAGuage <- renderPlotly({ fig <- plot_ly( domain = list(x = c(0, 1), y = c(0, 1)), value = prop_better, title = list(text = "D"), type = "indicator", color="black", gauge = list( bar = list( color = case_when( prop_better >= 75 ~ "green", prop_better >= 50 & prop_better < 75 ~ "orange", TRUE ~ "red" ) ), axis = list(range = list(0, 100), tickvals = c(0, 25, 50, 75, 100), ticktext = c("0", "25", "50", "75", "100")) ), mode = "gauge+number" ) fig <- fig %>% layout( margin = list(l=0,r=0), paper_bgcolor = "#f0f0f0", font = list(color = "darkblue", family = "Arial")) }) } ##################################SHINY APP shinyApp(ui = ui, server = server)
解决方案
问题根源在于Plotly仪表盘默认存在上下边距,且Shiny组件的高度设置未完全统一,fluidRow的固定高度限制了自适应能力。以下是具体修复步骤:
- 统一
plotlyOutput高度设置:给所有plotlyOutput添加height="100%",确保它们继承父容器高度 - 消除Plotly图表的上下边距:在每个图表的
layout中,将margin设置为list(l=0, r=0, t=0, b=0),移除默认的上下留白 - 统一图表布局高度:给每个Plotly图表的
layout添加height="100%",确保图表占满容器 - 让fluidRow自适应高度:移除fluidRow的固定
height:200px,改用min-height:200px保证最小高度,同时添加display: flex; align-items: stretch确保列内元素完全填充高度 - 设置
withSpinner继承高度:给withSpinner添加style="height:100%;",让加载动画容器也占满父元素
修改后的完整代码
main_content_MATDetail <- mainPanel( fluidRow( style = "background-color: #f0f0f0; min-height:200px; display: flex; align-items: stretch;", column(3, plotlyOutput("OAGuage", height="100%") %>% withSpinner(color = "#12436D", style="height:100%;")), column(3, plotlyOutput("UAGuage", height="100%") %>% withSpinner(color = "#12436D", style="height:100%;")), column(3, plotlyOutput("AAGuage", height="100%") %>% withSpinner(color = "#12436D", style="height:100%;")), column(3, plotlyOutput("PAGuage", height="100%") %>% withSpinner(color = "#12436D", style="height:100%;")) ) ) ui <- fluidPage( tabsetPanel( id = "main_tabs", tabPanel("Details ", titlePanel(div("Details", style = "font-size:18px;")), main_content_MATDetail )) ) #end of fluid page server <- function(input, output, session){ count_more<-9 count_less<-17 denominator<-(count_more+count_less) prop_better <- (100 * count_less/denominator) # 封装仪表盘生成函数,避免重复代码 create_gauge <- function(title_text) { fig <- plot_ly( domain = list(x = c(0, 1), y = c(0, 1)), value = prop_better, title = list(text = title_text), type = "indicator", gauge = list( bar = list( color = case_when( prop_better >= 75 ~ "green", prop_better >= 50 & prop_better < 75 ~ "orange", TRUE ~ "red" ) ), axis = list(range = list(0, 100), tickvals = c(0, 25, 50, 75, 100), ticktext = c("0", "25", "50", "75", "100")) ), mode = "gauge+number" ) fig %>% layout( margin = list(l=0, r=0, t=0, b=0), height = "100%", paper_bgcolor = "#f0f0f0", font = list(color = "darkblue", family = "Arial") ) } output$OAGuage <- renderPlotly(create_gauge("A")) output$AAGuage <- renderPlotly(create_gauge("B")) output$UAGuage <- renderPlotly(create_gauge("C")) output$PAGuage <- renderPlotly(create_gauge("D")) } ##################################SHINY APP shinyApp(ui = ui, server = server)
另外,代码中封装了create_gauge函数,减少了重复代码,后续修改仪表盘样式只需调整这个函数即可。
内容的提问来源于stack exchange,提问作者sophieflo
相关产品推荐
相关产品推荐

