如何让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应用,下图分别是该屏幕和更大屏幕的显示效果:

请问有什么方法可以让图表适配屏幕大小?
解决方案
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
相关产品推荐
相关产品推荐

