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

如何用Shiny与sortable实现可滚动bucket_list并添加滚动条

实现Shiny Sortable列表的滚动与自动滚动功能

问题背景

已通过style设置将排序容器(如rank_list_1)的max-height固定为700px,需实现两个需求:

  • 列表内容过长时,容器右侧显示垂直滚动条
  • 正确配置SortableJS的Autoscroll功能,拖拽元素靠近容器边缘时自动滚动

解决方案

1. 添加CSS实现容器滚动

针对sortable组件的内部列表容器,添加CSS样式限制高度并开启垂直滚动:

.sortable-list {
  max-height: 650px; /* 预留标题空间,比容器max-height小一些 */
  overflow-y: auto;
  overflow-x: hidden;
}

2. 配置SortableJS Autoscroll选项

在sortable_options中启用autoscroll,并设置合适的参数(可根据需求调整):

sortable_options(
  group = "mygroup",
  autoscroll = TRUE,
  scrollSpeed = 10,
  scrollSensitivity = 20
)
  • autoscroll: 设为TRUE启用自动滚动
  • scrollSpeed: 自动滚动的速度
  • scrollSensitivity: 鼠标距离容器边缘多少像素时触发自动滚动

修改后的完整代码

library(shiny)
library(sortable)

ui <- fluidPage(
  tags$head(
    tags$style(HTML("
      .bucket-list-container {min-height: 350px;}
      .sortable-list {
        max-height: 650px;
        overflow-y: auto;
        overflow-x: hidden;
      }
    "))
  ),
  fluidRow(
    column(
      width = 12,
      # 选择变量列表
      radioButtons(
        inputId = "variableList",
        label = "选择变量列表",
        choices = c("mtcars变量名" = "names(mtcars)", "美国州名" = "state.name")
      ),
      # 输入文本筛选列表项
      textInput(
        inputId = "subsetChooseListText",
        label = "输入文本筛选可选列表项",
        value = "c"
      ),
      div(
        class = "bucket-list-container default-sortable",
        "将元素拖拽到任意目标桶中",
        div(
          class = "default-sortable bucket-list bucket-list-horizontal",
          uiOutput("selection_list", style = "flex:1 0 200px;"),
          rank_list(
            text = "拖到这里",
            labels = list(),
            input_id = "rank_list_2",
            options = sortable_options(
              group = "mygroup",
              autoscroll = TRUE,
              scrollSpeed = 10,
              scrollSensitivity = 20
            )
          ),
          rank_list(
            text = "也可以拖到这里",
            labels = list(),
            input_id = "rank_list_3",
            options = sortable_options(
              group = "mygroup",
              autoscroll = TRUE,
              scrollSpeed = 10,
              scrollSensitivity = 20
            )
          )
        )
      )
    )
  ),
  fluidRow(
    column(
      width = 12,
      tags$b("结果"),
      column(
        width = 12,
        tags$p("input$rank_list_1"),
        verbatimTextOutput("results_1"),
        tags$p("input$rank_list_2"),
        verbatimTextOutput("results_2"),
        tags$p("input$rank_list_3"),
        verbatimTextOutput("results_3")
      )
    )
  )
)

server <- function(input,output) {
  
  # 响应式获取变量列表
  varList <- reactive({
    req(input$variableList)
    if (input$variableList == "state.name") {
      state.name
    } else {
      paste0(rep(names(mtcars), 20), "_", 1:220)
    }
  })
  
  # 响应式筛选列表项
  subsetChooseList <- reactive({
    items <- varList()
    pattern <- input$subsetChooseListText
    if (nchar(pattern) < 1) {
      return(items)
    }
    items[grepl(x = items, pattern = pattern, ignore.case = TRUE)]
  })
  
  output$selection_list <- renderUI({
    labels <- subsetChooseList()
    # 移除已被选中的项
    labels <- labels[!(labels %in% input$rank_list_2 | labels %in% input$rank_list_3)]
    rank_list(
      text = "从这里拖拽",
      labels = labels,
      input_id = "rank_list_1",
      options = sortable_options(
        group = "mygroup",
        autoscroll = TRUE,
        scrollSpeed = 10,
        scrollSensitivity = 20
      )
    )
  })
  
  # 调试用输出
  output$results_1 <- renderPrint(input$rank_list_1)
  output$results_2 <- renderPrint(input$rank_list_2)
  output$results_3 <- renderPrint(input$rank_list_3)
  
}

shinyApp(ui, server)

说明

  • CSS中.sortable-list是sortable组件内部列表的默认类名,设置max-height和overflow-y:auto后,内容超出时自动显示滚动条
  • 所有rank_list都配置了Autoscroll选项,拖拽元素靠近容器边缘时会自动滚动容器,提升拖拽体验

内容的提问来源于stack exchange,提问作者Roman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 02:35:09