css - 如何根据 rshiny 中的用户输入切换外部 css 文件?

标签 css r shiny

我希望在我的应用程序中构建暗模式。我意识到我们可以使用 bs_theme() 实现这一目标,但我的应用程序在外部 css 文件中有更多设置,当我使用 bs_theme() 时无法读取这些设置。

我想要 2 个单独的 CSS 文件,一个用于浅色主题,一个用于深色主题。根据用户输入,相关的主题文件应该加载到我的 Rshiny 应用程序中。关于如何做到这一点有什么建议吗?

最佳答案

我会创建两个不同的 css classes在这种情况下。

Here您将了解如何将 css 文件(任意多)包含到 Shiny 的应用程序中。

要在类之间切换,我们可以使用 library(shinyjs) 中的 addCssClass/removeCssClass(或 toggleCssClass) >:

library(shiny)
library(shinyjs)

if(!dir.exists("www")){
  dir.create("www")
}

writeLines(".dark {
  background-color: black;
  color: white; /* text color */
}", con = "www/dark_mode.css")

writeLines(".light {
  background-color: white;
  color: black; /* text color */
}", con = "www/light_mode.css")

ui <- fluidPage(
  useShinyjs(),
  tags$head(
    tags$link(rel = "stylesheet", type = "text/css", href = "dark_mode.css"),
    tags$link(rel = "stylesheet", type = "text/css", href = "light_mode.css")
  ),
  radioButtons("mode", "Select mode", choices = c("dark", "light"), selected  = "light")
)

server <- function(input, output, session) {
  observeEvent(input$mode, {
    if(input$mode == "dark"){
      addCssClass(class = "dark", selector = "body")
      removeCssClass(class = "light", selector = "body")
    } else {
      addCssClass(class = "light", selector = "body")
      removeCssClass(class = "dark", selector = "body")
    }
  })
}

shinyApp(ui, server)

result

同样可以通过 Shiny.addCustomMessageHandler 完成和一些自定义 JS 使用例如element.classList.add("myclass");(参见 this)。


编辑:将addCssClass应用于不同类的输入:

library(shiny)
library(shinyjs)

if(!dir.exists("www")){
  dir.create("www")
}

writeLines(".dark {
  background-color: black !important;
  color: white; /* text color */
}", con = "www/dark_mode.css")

writeLines(".light {
  background-color: white !important;
  color: black; /* text color */
}", con = "www/light_mode.css")

ui <- fluidPage(
  useShinyjs(),
  tags$head(
    tags$link(rel = "stylesheet", type = "text/css", href = "dark_mode.css"),
    tags$link(rel = "stylesheet", type = "text/css", href = "light_mode.css")
  ),
  radioButtons("mode", "Select mode", choices = c("dark", "light"), selected  = "light"),
  selectizeInput("Test", "Test Input", choices = 1:10),
  actionButton("testButton", "Test Button")
)

server <- function(input, output, session) {
  observeEvent(input$mode, {
    applyTo <- list(".selectize-input", ".btn-default")
    if(input$mode == "dark"){
      lapply(applyTo, function(x){
        addCssClass(class = "dark", selector = x)
        removeCssClass(class = "light", selector = x)
      })
    } else {
      lapply(applyTo, function(x){
        addCssClass(class = "light", selector = x)
        removeCssClass(class = "dark", selector = x)
      })
    }
  })
}

shinyApp(ui, server)

result


编辑:使用forEach:

library(shiny)
library(shinyjs)

if(!dir.exists("www")){
  dir.create("www")
}

writeLines(".dark {
  background-color: black !important;
  color: white; /* text color */
}", con = "www/dark_mode.css")

writeLines(".light {
  background-color: white !important;
  color: black; /* text color */
}", con = "www/light_mode.css")

ui <- fluidPage(
  useShinyjs(),
  tags$head(
    tags$link(rel = "stylesheet", type = "text/css", href = "dark_mode.css"),
    tags$link(rel = "stylesheet", type = "text/css", href = "light_mode.css")
  ),
  radioButtons("mode", "Select mode", choices = c("dark", "light"), selected  = "light"),
  selectizeInput("Test", "Test Input", choices = 1:10),
  actionButton("testButton", "Test Button")
)

server <- function(input, output, session) {
  
  dm_classes <- paste(c(".selectize-input", ".btn-default"), collapse = ", ")
  
  observeEvent(input$mode, {
    if(input$mode == "dark"){
      runjs(sprintf("document.querySelectorAll('%s').forEach(x=>x.classList.add('dark'));
                     document.querySelectorAll('%s').forEach(x=>x.classList.remove('light'));", dm_classes, dm_classes))
    } else {
      runjs(sprintf("document.querySelectorAll('%s').forEach(x=>x.classList.add('light'));
                     document.querySelectorAll('%s').forEach(x=>x.classList.remove('dark'));", dm_classes, dm_classes))
    }
  })
}

shinyApp(ui, server)

关于css - 如何根据 rshiny 中的用户输入切换外部 css 文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71009828/

相关文章:

r - dplyr 使用 if else 有条件地按组过滤

rbind 具有不同行长的文本文件

r - 如何对排名数据建模

r - 如何在 R/Shiny 中布局动态生成的 UI 元素?

html - 为什么背景图片有时没有覆盖整个页面?

html - 我怎样才能给我的全高元素?CSS

html - 透明背景和标志

CSS:悬停由于不透明而不起作用

javascript - 如何区分 R/Shiny 可 react javascript 回调中的按钮?

javascript - 在 Shiny 的应用程序中动态选择多个选项卡