首页 > 解决方案 > 删除shinydashboardPlus中右侧边栏宽度更改时出现的多余空间

问题描述

我正在使用shinydashboardPlus并希望更改右侧边栏的宽度,我知道这可以通过在函数width调用中指定参数来完成rightSidebar,但是当我这样做时(根据以下示例取自此处)旁边会出现冗余空间右侧菜单(请参阅下面屏幕截图中右侧菜单旁边的深灰色列/空间)。

library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)

data(iris)
mychoices <- c("pick me A", 
               "pick me - a very long name here", 
               "no pick me - B", 
               "another one that is long")

## my css
CSS <- function(colors){
  template <- "
.checkboxGroupButtons div.btn-group:nth-child(%s) button {
  background: %s !important;
  color: black !important;
  padding: 5px;
  margin-bottom: 8px
}"
  paste0(
    apply(cbind(seq_along(colors), colors), 1, function(vc){
      sprintf(template, vc[1], vc[2])
    }),
    collapse = "\n"
  )
}
cols <- c("red", "blue", "yellow", "green")
mycss <- CSS(cols)


# ui <- tagList(
header <- dashboardHeaderPlus(enable_rightsidebar = TRUE,
                              rightSidebarIcon = "filter")
sidebar <- dashboardSidebar(
  p(strong("Classes")),
  actionButton(inputId = "selectall", label="Select/Deselect all",
               style='padding:12px; font-size:80%'),
  br(), br(),
  checkboxGroupButtons(
    inputId = "classes",
    choices = mychoices,
    selected = mychoices,
    direction = "vertical",
    width = "100%",
    size = "xs",
    checkIcon = list(
      yes = icon("ok", 
                 lib = "glyphicon"))
  )
)

body <- dashboardBody(
  tags$script('
      $(".navbar-custom-menu").on("click",function(){
        $(window).trigger("resize");
      })'
  ),
  tags$head(tags$style(HTML('
         /* logo */
        .skin-blue .main-header .logo {
          background-color: #808080;
        }
        /* logo when hovered */
        .skin-blue .main-header .logo:hover {
          background-color: #FFFFFF;
        }
         /* navbar (rest of the header) */
        .skin-blue .main-header .navbar {
                              background-color: #C0C0C0;
        }
        /* main sidebar */
        .skin-blue .main-sidebar {
                              background-color: #FFFFFF;
        }
        /* body */
        .content-wrapper, .right-side {
                            background-color: #FFFFFF;
                            }                   
                         
      '))),
  tags$head(tags$style(HTML(mycss))),
  tabsetPanel(type = "tabs",
              tabPanel("Scatter", id = "panel1",
                       plotOutput(outputId = "scatter")),
              tabPanel("PCA", id = "panel2"))
)

rightsidebar <- rightSidebar(background = "light",
                             width = 150,
                             .items = list(
                               p(strong("Controls")),
                               br(),
                               p("Transparancy"),
                               sliderInput("trans", NULL,
                                           min = 0,  max = 1, value = .5),
                               actionButton("resetButton", "Zoom/reset plot", 
                                            style='padding:6px; font-size:80%'),
                               br(), br(),
                               actionButton("clear", "Clear selection", 
                                            style='padding:6px; font-size:80%'),
                               br(), br(),
                               actionButton("resetColours", "Reset colours", 
                                            style='padding:6px; font-size:80%'),
                               br())
                             )
                             

ui <- dashboardPagePlus(header,
                        sidebar,
                        body,
                        rightsidebar,
                        sidebar_fullCollapse = TRUE)

shinyUI(tagList(ui))

## server side
server <- function(input, output) {
  output$scatter <- renderPlot({
    plot(iris$Petal.Length, iris$Petal.Width, pch=21)
    cats <- levels(iris$Species)
    cols <- c("red", "blue", "yellow2")
    ind <- lapply(cats, function(z) which(iris$Species == z))
    for (i in seq(cats)) {
      points(iris$Petal.Length[ind[[i]]], iris$Petal.Width[ind[[i]]], 
             pch = 19, col = cols[i])
    }
  })
}

## run app
shinyApp(ui, server)

在此处输入图像描述

我的预感是我需要更改应用程序中某些元素的背景颜色,因为这种灰色是默认主题颜色shinydashboardPlus(您可以看到我已经使用一点 将其更改为白色css)。

我想要实现的是这个(但右侧菜单的宽度更小) - 这是width未指定且使用默认值时的输出。

在此处输入图像描述

 sessionInfo()
R version 4.0.2 (2020-06-22)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.6

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8

attached base packages:
[1] stats4    parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] shinyWidgets_0.5.3       dendextend_1.14.0        tidyr_1.1.2             
 [4] patchwork_1.0.1          ggplot2_3.3.2            shinyhelper_0.3.2       
 [7] colorspace_1.4-1         colourpicker_1.1.0       shinythemes_1.1.2       
[10] DT_0.15                  dplyr_1.0.2              shinydashboardPlus_0.7.5
[13] shinydashboard_0.7.1     shiny_1.5.0              MSnbase_2.14.2          
[16] ProtGenerics_1.20.0      S4Vectors_0.26.1         mzR_2.22.0              
[19] Rcpp_1.0.5               Biobase_2.48.0           BiocGenerics_0.34.0   

标签: cssrshinyshinydashboard

解决方案


经过一番挖掘,我发现错误从AdminLTE.min.css文件的第 7 行开始上升,其中它为230px打开的控件侧边栏提供了右边距,并且230px是默认宽度:

.control-sidebar-open .content-wrapper, .control-sidebar-open .main-footer, .control-sidebar-open .right-side {
    margin-right: 230px;
}

这个边距需要等于选择的宽度,一种解决方法是使用这个pastecss(..., width)函数,它只是一个包装器,但附加了提供正确边距paste0的已编辑 css :control-bar

pastecss <- function(..., width) paste0(...,'\n', ' .control-sidebar-open .content-wrapper,.control-sidebar-open .main-footer,.control-sidebar-open .right-side{
                margin-right:',width,'px
            }')

然后在创建 body 元素时调用它:

body <- dashboardBody(
  tags$script('
      $(".navbar-custom-menu").on("click",function(){
        $(window).trigger("resize");
      })'
  ),
  tags$head(tags$style(HTML(pastecss('
         /* logo */
        .skin-blue .main-header .logo {
          background-color: #808080;
        }
        /* logo when hovered */
        .skin-blue .main-header .logo:hover {
          background-color: #FFFFFF;
        }
         /* navbar (rest of the header) */
        .skin-blue .main-header .navbar {
                              background-color: #C0C0C0;
        }
        /* main sidebar */
        .skin-blue .main-sidebar {
                              background-color: #FFFFFF;
        }
        /* body */
        .content-wrapper, .right-side {
                            background-color: #FFFFFF;
                            }               
      ',width= 150)))),
  tags$head(tags$style(HTML(mycss))),
  tabsetPanel(type = "tabs",
              tabPanel("Scatter", id = "panel1",
                       plotOutput(outputId = "scatter")),
              tabPanel("PCA", id = "panel2"))
)

更好的方法

另一种方法,我将把它推送到 github repo 是重载 rightSidebar 函数:

rightSidebar <- function(..., background = "dark", width = 230, .items = NULL) {
  
  panels <- list(...)
  
  sidebarTag <- shiny::tags$div(
    id = "controlbar",
    shiny::tags$aside(
      class = paste0("control-sidebar control-sidebar-", background),
      style = paste0("width: ", width, "px;"),
      # automatically create the tab menu
      if (length(panels) > 0) shinydashboardPlus:::rightSidebarTabList(shinydashboardPlus:::rigthSidebarPanel(...)),
      if (length(panels) > 0) shinydashboardPlus:::rigthSidebarPanel(...) else shinydashboardPlus:::rigthSidebarPanel(.items)
    ),
    # Add the sidebar background. This div must be placed
    # immediately after the control sidebar
    shiny::tags$div(class = "control-sidebar-bg", style = paste0("width: ", width, "px;"))
  )
  
  shiny::tagList(
    shiny::singleton(
      shiny::tags$head(
        # custom css to correctly handle the width of the rightSidebar
        shiny::tags$style(
          shiny::HTML(
            paste0(
              ".control-sidebar-bg,
               .control-sidebar {
                  top: 0;
                  right: ", -width, "px;
                  width: ", width, "px;
                  -webkit-transition: right 0.3s ease-in-out;
                  -o-transition: right 0.3s ease-in-out;
                  transition: right 0.3s ease-in-out;
                }
                .control-sidebar-open .content-wrapper,.control-sidebar-open .main-footer,.control-sidebar-open .right-side{
                  margin-right:",width,"px
                }"
            )
          )
        )
      )
    ),
    sidebarTag
  )
}

然后在加载后执行它shinydashboardPlus以避免冲突,然后像往常一样执行你的代码。


推荐阅读