如何修改Shiny应用中内容面板的背景颜色?
解决Shiny+Plotly应用黑色背景适配问题
我用Plotly开发了一款Shiny饼图应用,用来展示阿根廷罗萨里奥港向50多个国家出口大豆的情况。应用支持通过URL后缀/?COUNTRY=X查询指定国家的数据,并且以iframe形式嵌入网站侧边栏。目前所有功能正常,但网站背景是黑色,应用的内容面板(饼图自身背景及下方出口商列表背景)还是亮白色,和网站风格冲突。之前尝试在fluidPage里加style = "background-color: black;",只能修改网页背景,没法改变内容面板的颜色。

要解决这个问题,需要分别调整Plotly图表本身的背景和Shiny内容容器的样式,具体步骤如下:
1. 修改Plotly图表背景
在Plotly的layout配置中,添加paper_bgcolor(图表容器背景)和plot_bgcolor(绘图区域背景)为黑色,同时调整标题、图例、饼图内部文本的颜色为浅色,避免在黑色背景上看不清:
layout( title = list( text = paste("Port of Rosario to", unique(df$COUNTRY)), font = list(color = "#FFFFFF") # 设置标题为白色 ), legend = list( orientation = "h", xanchor = "center", x = 0.5, font = list(color = "#FFFFFF") # 设置图例文本为白色 ), autosize = T, xaxis = list(showticklabels = F), paper_bgcolor = "#000000", # 图表容器背景设为黑色 plot_bgcolor = "#000000" # 绘图区域背景设为黑色 )
2. 修改Shiny内容容器样式
在fluidPage中添加自定义CSS,覆盖shinythemes的cyborg主题中默认的白色内容面板背景:
ui <- fluidPage( theme = shinytheme("cyborg"), # 添加自定义CSS tags$head( tags$style(HTML(" .container-fluid { background-color: #000000; } .plotly { background-color: #000000; } ")) ), titlePanel(h3( "SOYBEANS", align = "center", style = "color: #FFFFFF;")), # 标题文本设为白色 column(8, align="center",offset = 0, plotlyOutput("granos_exportados", width = "350px", height = "600px")) )
完整修改后的代码
#### packages #### library(plotly) library(shiny) library(shinythemes) library(dplyr) # 补充依赖包,支持管道符和筛选函数 library(tidyr) # 补充依赖包,支持数据重塑函数 #### TO TEST LOCALLY, use "/?COUNTRY=X", eg http://localhost:PORT/?COUNTRY=CHINA (replace PORT with the appropriate port number). #### #### load data #### granos_exportados <- read.csv(file = "https://s3.us-east-2.amazonaws.com/ecotopia.today/Data/exportadores_rosario.csv") #### shiny UI #### ui <- fluidPage( theme = shinytheme("cyborg"), # 自定义CSS解决背景问题 tags$head( tags$style(HTML(" .container-fluid { background-color: #000000; } .plotly { background-color: #000000; } ")) ), titlePanel(h3( "SOYBEANS", align = "center", style = "color: #FFFFFF;")), column(8, align="center",offset = 0, plotlyOutput("granos_exportados", width = "350px", height = "600px")) ) #### shiny server or Backend #### server <- function(input, output, session) { query <- reactive({ parseQueryString(session$clientData$url_search) }) output$granos_exportados <- renderPlotly({ df <- granos_exportados %>% filter(COUNTRY == query()[['COUNTRY']]) %>% gather(grain_exporter, quantity, -COUNTRY) %>% mutate(quantity_percent = quantity/sum(quantity)) plot_ly(df, labels = ~ grain_exporter, values = ~ quantity, type = 'pie', text = ~paste(round(quantity/1000, 2), " toneladas"), textinfo = 'percent', textposition='inside', hovertemplate = "%{label}<br>%{value:,.2f} toneladas de soja<extra></extra>", marker = list(colors = c("#267278","#65338D","#4770B3",'#D21F75','#383689','#50AED3','#48B24F', '#E57438','#569DD2','#569D79','#58595B','#E4B031','#84D2F4','#CAD93F', '#F5C8AF','#9AC4B3','#9E9EA2'), line = list(color = '#FFFFFF', width = 1)), textfont = list(color = "#FFFFFF")) %>% # 饼图内部文本设为白色 layout(title = list( text = paste("Port of Rosario to", unique(df$COUNTRY)), font = list(color = "#FFFFFF") ), legend = list(orientation = "h", xanchor = "center", x = 0.5, font = list(color = "#FFFFFF")), autosize = T, xaxis = list(showticklabels = F), paper_bgcolor = "#000000", plot_bgcolor = "#000000") %>% plotly::config(displaylogo = F) %>% htmlwidgets::onRender("function(el,x){el.on('plotly_legendclick', function(){ return false; })}") }) } #### RUN THE APP #### shinyApp(ui, server)
内容的提问来源于stack exchange,提问作者Brian Holmes
相关产品推荐
相关产品推荐

