You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Shiny应用中的图表尺寸适配不同屏幕大小?

问题描述

无法提供最小可复现示例,因数据库规模庞大且代码冗长。以下是我的sidebarPanel代码:

dashboardSidebar(width = 250,
                   div(style="font-size:10px;",
                                   sidebarMenu(
                                     menuItem( "Analyse de la concurrence",
                                               menuSubItem("Cartographie sur les hopitaux", tabName = "StatHopital"),
                                               menuSubItem("Cartographie sur les communes",tabName = "StatCommune"),

                                                           div(style="font-size:12px;",


                                                               selectInput("LibGHM", 
                                                                           label = div(style = "display: flex; align-items: center;",
                                                                                       HTML(paste0('<i class="fas fa-user-md" style="color: white; margin-right: 5px;" title="Doctor"></i>')),
                                                                                       "Spécialités"),
                                                                           choices = c("Total",levels(as.factor(sejdig$Libéllé.CHIC))),
                                                                           selected="Total"
                                                               ),
                                                               

                                                               uiOutput("ui"),

                                                               
                                                                
                                                               selectInput("Urgence", 
                                                                           label = div(style = "display: flex; align-items: center;",
                                                                                       HTML(paste0('<i class="fas fa-ambulance" style="color: white; margin-right: 5px;" title="Ambulance"></i>')),
                                                                                       "Urgence"),
                                                                           choices = c("Total",levels(as.factor(sejdig$Urgence))),
                                                                           selected="Total"
                                                               ),

                                                               # selectInput(inputId = "Majorite",label="Catégories d'âge",choices = c("Total",levels(as.factor(sejdig$Majorite))),
                                                               #             selected="Total"),
                                                                
                                                               selectInput("Majorite", 
                                                                           label = div(style = "display: flex; align-items: center;",
                                                                                       HTML(paste0('<i class="fas fa-user" style="color: white; margin-right: 10px;" title="Doctor"></i>')),
                                                                                       HTML(paste0('<i class="fas fa-child" style="color: white; margin-right: 5px;" title="Child"></i>')),
                                                                                       "Majorité"),
                                                                           choices = c("Total",levels(as.factor(sejdig$Majorite))),
                                                                           selected="Total"
                                                               ),

                                                               selectInput(inputId = "Zone",
                                                                           label=div(style = "display: flex; align-items: center;",
                                                                                  HTML(paste0('<i class="fas fa-bullseye" style="color: white; margin-right: 5px;" title="Child"></i>')),
                                                                                  "Seuil de Zone de récrutement"),
                                                                           choices = c("Ensemble des patients","Zone de recrutement","Zone d'attraction"),
                                                                           selected="Zone de recrutement"),
                                                                

                                                               selectInput(inputId ="indicateur",div(style = "display: flex; align-items: center;",
                                                                           HTML(paste0('<i class="fas fa-chart-line" style="color: white; margin-right: 5px;" title=""></i>')),
                                                                           "Indicateurs"),
                                                                           choices = c("Nombre de patients"="nb_patient_tot",
                                                                                       "Nombre de patients rapporté à la population"="nb_patient_pop")))


                                                           )




                                   )
  )
  )

以及dashboardBody代码:

dashboardBody(
    tags$style(type = "text/css",
               "html, body {width:100%;height:100%}",

               ".leaflet .legend {
                                         font-size: 8px;
                                       line-height: 6px;}",

               ".leaflet .legend i{
                                       width: 8px;
                                       height: 8px;
                                       }"
    ),

    tabItems(

      tabItem(
        tabName = "StatHopital",div(style="font-size:11px;width: 1200px; height: 700px",

                                    fluidRow(box(selectInput(inputId = "Hopital1",choices = c(listeHop),
                                                             label = "Choisir l'hôpital 1"),
                                                 width = 6,height = 70,
                                                 solidHeader = TRUE),
                                             box(selectInput(inputId = "Hopital2",choices = rev(c(listeHop)),
                                                             label = "Choisir l'hôpital 2"),
                                                 width = 6,height = 70,
                                                 solidHeader = FALSE)),
                                    fluidRow( tabsetPanel(
                                      tabPanel("Zone de recrutement",
                                               box(leafletOutput("ZoneHop1",height = 500,width = "100%")),
                                               box(leafletOutput("ZoneHop2",height = 500,width = "100%"))
                                      ),
                                      tabPanel("Part de marché", 
                                               box(leafletOutput("MktShareZ1",height = 500,width = "100%")),
                                               box(leafletOutput("MktShareZ2",height = 500,width = "100%"))
                                               ),
                                      tabPanel("Concurrence", leafletOutput("Comp1",height = 600,width = "100%"))
                                    ))
        )),

      tabItem(
        tabName = "StatCommune",div(style="font-size:11px;",

                                    fluidRow(box(selectInput(inputId = "Commune",choices = c(levels(as.factor(LibCom$libgeo_cp))),
                                                             label = "Choisir la commune"),
                                                 width = 6,height = 70,
                                                 solidHeader = TRUE)),
                                    fluidRow( tabsetPanel(
                                      tabPanel("Nombre de séjours par communes",
                                               leafletOutput("sejourCom",height = 550)
                                      ),
                                      tabPanel("Concurrence au sein de la commune",
                                               leafletOutput("HHI_IDF",height = 550)
                                      ),
                                      tabPanel("Flux des communes vers les hopitaux",
                                               leafletOutput ("Commune2",height = 550)),
                                      tabPanel("Flux des communes vers les hopitaux",
                                               dataTableOutput ("Commune3"))
                                    ))
        ))
    )


    )
)

切换到更大屏幕时,图表尺寸仍保持不变。我在1920x1080分辨率的电脑上开发该Shiny应用,下图分别是该屏幕和更大屏幕的显示效果:
1920x1080屏幕显示效果
更大屏幕显示效果

请问有什么方法可以让图表适配屏幕大小?


解决方案

1. 移除固定宽度限制

你的StatHopital标签页外层div设置了固定宽度width:1200px,这是大屏下内容无法拉伸的核心原因,直接删除该固定宽度:

tabItem(
  tabName = "StatHopital",div(style="font-size:11px; height: 700px", # 移除width:1200px
  ...)

2. 用相对高度替代固定像素值

当前图表高度都是固定像素(如height=500),换成视口高度单位vh(1vh=屏幕高度的1%),实现高度自适应:

# 示例:将固定高度改为相对高度
leafletOutput("ZoneHop1",height = "70vh",width = "100%")

可以根据布局需求调整vh数值,比如70vh表示占屏幕高度的70%。

3. 优化盒子布局的响应性

保留fluidRow和box的width参数(如width=6),让Shiny的栅格系统自动适配屏幕宽度;避免给box设置固定宽度,确保它能在大屏下填满对应列空间。

4. 增强全局自适应样式

在tags$style中补充样式,确保内容填满可用空间:

tags$style(type = "text/css",
           "html, body {width:100%;height:100%;margin:0;padding:0}",
           ".content-wrapper {height: 100%; overflow: auto;}",
           ".tab-content {height: calc(100% - 80px);}", /* 减去顶部控件高度 */
           ".leaflet .legend {font-size: 8px; line-height: 6px;}",
           ".leaflet .legend i{width: 8px; height: 8px;}"
)

5. 动态监听窗口大小(进阶可选)

如果需要更精细的控制,可使用shinyjs监听窗口 resize 事件,动态重绘图表:
首先加载包并初始化:

library(shinyjs)

# 在UI中添加
useShinyjs()

然后在server中添加监听:

observeEvent(input$clientdata_output_ZoneHop1_width, {
  output$ZoneHop1 <- renderLeaflet({
    # 你的leaflet绘制逻辑
  })
})

内容的提问来源于stack exchange,提问作者Seydou GORO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:22:03