如何用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
相关产品推荐
相关产品推荐

