如何在R Plotly中固定横向柱状图的柱高并实现垂直滚动?
Plotly横向柱状图固定柱高+滚动实现问题
不确定该问题是否曾被提出,我多方寻找解决方案均未获得有效结果。
我正在使用Plotly开发一款Shiny仪表盘,已经为图表预留了固定的展示空间,该图表为展示多分类数据的横向柱状图。
以下是最小可复现代码:
library(tidyverse) library(plotly) tibble(Category = str_c("Category ", seq(1, 20, 1)), Value = runif(20)) %>% plot_ly( y = ~ Category, x = ~ Value, type = "bar", hoverinfo = "text", hovertemplate = ~paste0( "Category: ", Category, "<br>", "Value: ", Value, "<extra></extra>" ), marker = list( line = list(color = "#000000", width = 1) ) ) %>% layout( autosize = FALSE, showlegend = FALSE, xaxis = list( title = "Value" ), yaxis = list( title = "" ) )
目前遇到的问题是分类数量不固定:本示例中为20个,最多可达100个。我想要实现的效果是:无论分类数量多少,每根横向柱子的高度都保持固定,分类数量较多时自动出现垂直滚动条以容纳更多柱子,效果示例见:
目前公开的通用解决方案是通过固定公式动态计算图表高度:
plot_height <- 500 + 10*nrow(df)
但该方案并不符合我的需求:当仅存在1个分类时柱高过大,当存在1000个分类时柱子会细得像线条。我本以为固定横向柱状图的柱高是十分基础的功能,但在Plotly中实现难度极高,恳请各位给出可行的实现建议。
可行实现方案
可以结合Shiny CSS容器限制+Plotly动态高度计算(固定单柱高度)的方式实现,具体逻辑如下:
- 先固定单根柱子的高度,再叠加坐标轴、边距的固定高度,算出Plotly图表的实际总高度
- 用CSS给Plotly的外层容器设置最大高度和垂直滚动属性,保证预留空间不变,超出高度自动出现滚动条
完整实现代码
library(shiny) library(tidyverse) library(plotly) ui <- fluidPage( # 给plotly容器设置固定最大高度、垂直滚动 tags$style(HTML(" .plotly-container { max-height: 600px; /* 替换为你预留的展示空间高度 */ overflow-y: auto; overflow-x: hidden; } ")), div(class = "plotly-container", plotlyOutput("bar_plot") ) ) server <- function(input, output, session) { # 模拟数据,可替换为你的实际数据 df <- reactive({ # 可动态调整分类数量测试效果 n <- sample(1:100, 1) tibble(Category = str_c("Category ", seq(1, n, 1)), Value = runif(n)) }) output$bar_plot <- renderPlotly({ req(df()) # 固定参数设置 single_bar_height <- 30 # 你要固定的单根柱子高度,单位px,可自行调整 margin_height <- 100 # 上下边距+x轴标题等额外占用的高度,可自行调整 total_height <- single_bar_height * nrow(df()) + margin_height df() %>% plot_ly( height = total_height, # 动态设置图表总高度 y = ~ Category, x = ~ Value, type = "bar", hoverinfo = "text", hovertemplate = ~paste0( "Category: ", Category, "<br>", "Value: ", Value, "<extra></extra>" ), marker = list( line = list(color = "#000000", width = 1) ) ) %>% layout( autosize = FALSE, showlegend = FALSE, xaxis = list( title = "Value" ), yaxis = list( title = "", tickfont = list(size = 12) ) ) }) } shinyApp(ui, server)
方案说明
- 单柱高度完全由你设置的*
single_bar_height*参数控制,不会随分类数量变化变粗或变细 - 外层容器的
max-height固定了你预留的展示空间大小,当图表总高度小于这个值时,容器高度随图表高度自适应,不会出现空白;当图表总高度大于这个值时,自动出现垂直滚动条 - 即使分类数量多达100个,只要单柱高度固定,滚动查看的体验也符合预期
内容的提问来源于stack exchange,提问作者ComoDA
相关产品推荐
相关产品推荐

