【问题标题】:CSS for each page in R ShinyR Shiny中每个页面的CSS
【发布时间】:2015-10-04 05:23:17
【问题描述】:

我编写了一个闪亮的 R 应用程序,并在完成之前对其进行样式设置。我已经编写了少量的 HTML,并想使用 CSS 更改背景颜色等内容。 在线咨询后,我发现我需要使用 class 参数分隔我的 css,但是当我为每个页面指定一个类时,它根本没有带回任何 CSS。

下面是我的 R 闪亮应用程序的缩短版本。任何帮助将不胜感激。

library(shiny)

setwd("C:\\Users\\FRSAWG\\Desktop\\Application\\Shiny")

user <- shinyUI(navbarPage("",

tabPanel("Home Page",
       div(class="one",
         div(tags$style("#one body{background-color:blue;color:white;font-family:Arial}"),
            div(HTML("<h1><b><center>Home Page</center></b></h1>"))))),
tabPanel("Glossary",
       div(class="two",
           div(tags$style("#two body{background-color:red;color:white;font-family:Arial}"),
               div(HTML("<h1><b><center>Glossary</center></b></h1>")))))
))

serv <- shinyServer(function(input, output) {})

shinyApp(user, serv)

作为参考,我为每个页面指定了一个两个类名。

【问题讨论】:

  • 查看我的更新答案 - 摆脱了我之前建议中有时出现的闪烁。

标签: html css r user-interface shiny


【解决方案1】:

更新: 使用 Dean Attali (link) 的包 shinyjs,我编写了一个帮助函数,您可以从 R 调用它来创建和运行一个 jQuery 函数来修改 CSS 元素基于来自 R 语法的输入的给定对象(或选择器,通常)。当标签更改时,您可以使用它来修改&lt;body&gt;的CSS。

这解决了我之前建议的问题 - 现在不需要切换 body 的类,当&lt;body&gt; 的所有样式类都被关闭时,有时会导致闪烁。

下面是工作示例:

library(shiny)
library(shinyjs)

## Modify the CSS style of a given selector
modifyStyle <- function(selector, ...) {

  values <- as.list(substitute(list(...)))[-1L]
  parameters <- names(values)

  args <- Map(function(p, v) paste0("'", p,"': '", v,"'"), parameters, values)
  jsc <- paste0("$('",selector,"').css({", paste(args, collapse = ", "),"});")

  shinyjs::runjs(code = jsc)

}

# UI for the app
user <- shinyUI(
  navbarPage(title = "", id = "navtab",
             header = div(useShinyjs()),
             tabPanel("Home Page",
                      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
                      "More text."
             ),

             tabPanel("Glossary",
                      div(HTML("<h1><b><center>Glossary</center></b></h1>")),
                      "More text."
             )
  )
)

# Server for the app
serv <- shinyServer(function(input, output, session) {

  observeEvent(input$navtab, {
    currentTab <- input$navtab # Name of the current tab

    if (currentTab == "Home Page") {
      modifyStyle("body", background = "blue", color = "white", 'font-family' = "Arial")
    }
    if (currentTab == "Glossary")  {
      modifyStyle("body", background = "red", color = "white", 'font-family' = "Arial")
    }
  })

})

shinyApp(user, serv)


我自己是 CSS 新手,但您的问题似乎可以通过稍微更改 CSS 标签来解决。将#one 更改为.one 并删除括号前的body 将使CSS 样式应用于one 类的div。

使用选择器#one 将更改 id 而非类为one 的 div 的 CSS 样式。这是a guide on w3shools.com 的链接,它解释了 CSS 语法中不同选择器的使用。

其他一些注意事项:

  • 你也可以使用tags$head来组织你的风格标签 一个地方,而不是在代码周围散布它们。 (不过,这取决于个人喜好。)
  • 您可以将 class 参数传递给 tabPanel 以设置其 CSS 类 - 这样就无需内部 div 来设置类。

修改后的示例代码:

library(shiny)

user <- shinyUI(navbarPage(
  tags$head(
    tags$style(HTML(".one {background-color: blue; color: white; font-family: Arial}")),
    tags$style(HTML(".two {background-color: red;  color: white; font-family: Arial}"))
  ),

  tabPanel("Home Page", class = "one",
      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
      "More text."
  ),

  tabPanel("Glossary", class = "two",
      div(HTML("<h1><b><center>Glossary</center></b></h1>")),
      "More text."
  )
))

serv <- shinyServer(function(input, output) {})

shinyApp(user, serv)

就像我提到的,我是 CSS 新手,所以我不能 100% 确定这是否是您正在寻找的输出。

EDIT2:这是一个解决方案,使用包shinyjs 在所选选项卡更改时更新&lt;body&gt; 的类。 (请注意,要使用shinyjs 中的功能,您需要在您的ui 中包含useShinyjs()。)

我们的想法是通过将navbarPage 的ID 设置为navtab,使navbarPage 返回input$navtab 中当前处于活动状态的选项卡的名称。然后我们可以使用 shinyjs 包中的 toggleClass 函数来动态更改 &lt;body&gt; 的类,从而应用适当的 CSS 样式。

这并不完美,因为类更改仅在服务器收到选项卡已更改的通知后发生,这有时会导致背景在更改之前闪烁。它可能会有点烦人。我怀疑更好的解决方案是在单击链接以更改选项卡时使用 javascript 更改 &lt;body&gt; 类,但我不知道如何使用 Shiny 来做到这一点。

代码如下:

library(shiny)
library(shinyjs)

user <- shinyUI(
  navbarPage(title = "", id = "navtab",
  header = tags$head(
    useShinyjs(),
    tags$style(HTML(".one {background: blue; color: white; font-family: Arial}")),
    tags$style(HTML(".two {background: red;  color: white; font-family: Arial}"))
  ),

    tabPanel("Home Page",
      div(HTML("<h1><b><center>Home Page</center></b></h1>")),
      "More text."
    ),

    tabPanel("Glossary",
     div(HTML("<h1><b><center>Glossary</center></b></h1>")),
     "More text."
    )
  )
)

serv <- shinyServer(function(input, output, session) {

   observeEvent(input$navtab, {
     shinyjs::toggleClass(selector = "body", class = "one",
                 condition = (input$navtab == "Home Page"))

     shinyjs::toggleClass(selector = "body", class = "two",
                 condition = (input$navtab == "Glossary"))
   })

})

shinyApp(user, serv)

【讨论】:

  • 这解决了我指定哪个“页面”接收哪种颜色的问题,但是运行此脚本意味着只有文本背景变为蓝色或红色,我希望在一页上将整个背景变为蓝色另一个是红色(因此是 body 参数)。
  • 我想你可能有,这就是我试图在我编辑的第二个代码 sn-p 中解决的问题。似乎我在某处犯了一个复制粘贴错误 - 我确信它正在工作昨天但现在似乎不起作用(例如,更改标签会改变除导航栏以外的所有内容的颜色)。
  • @Andrew 我使用 shinyjs 包中包含的 javascript 功能添加了一个更新的解决方案。它并不完美,但它会改变整个背景。
  • 只是关于使用 shinyjs 的评论:您使用 runjs 的解决方案非常漂亮和聪明,但我想指出,将来创建一个实际的 javascript 函数并调用它可能会更容易直接——查看shinyjs::extendShinyjs。感谢@MikkoM 对人们进行教育!
  • 好点 - 这可能是一个更优雅的解决方案。实际上,在想出这个之前,我曾考虑过使用extendShinyjs,但我不得不承认,我对 R 和 JS 之间的参数传递有点害怕——我才刚刚开始学习 jQuery,所以我不太适应还用 JS 编码。 PS。 shinyjs 包 @daattali 做得很好!我发现它真的很有帮助和鼓舞人心 - 使用它实际上是我想自己学习 JavaScript 的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2015-12-04
  • 1970-01-01
  • 2014-06-16
  • 2014-08-13
  • 2021-01-08
  • 2020-07-06
相关资源
最近更新 更多