You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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动态高度计算(固定单柱高度)的方式实现,具体逻辑如下:

  1. 先固定单根柱子的高度,再叠加坐标轴、边距的固定高度,算出Plotly图表的实际总高度
  2. 用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 07:15:03