如何在Shiny Dashboard中用线条/箭头连接Box实现树状图
问题描述
我希望通过Box组件复现下方的树状图效果,请问能否为这些Box添加类似图中的连接线或箭头,实现组件间的关联展示?

当前代码
library(shiny) library(shinydashboard) ui <- dashboardPage( dashboardHeader(title = "Connected Boxes"), dashboardSidebar(), dashboardBody( fluidRow( column(12, fluidRow( column(2,), column(5,), column(1,), column(4, box( title = "No ADC received", width = 12, height = 80, )) ), fluidRow( column(2,), column(5, box( title = "Trodelvy", width = 12, height = 80, style = "background-color: red; border-color: #red;", ) ), column(5,) ), fluidRow( column(2,), column(5,), column(1, ), column(4, box( title = "EV", width = 12, height = 80, style = "background-color: lightblue; border-color: #lightblue;", )) ), fluidRow( column(2, box( title = "Bladder", width = 12, height = 80, ) ), column(5,), column(5,) ), fluidRow( column(2,), column(5,), column(1,), column(4, box( title = "No ADC received", width = 12, height = 80, )) ), fluidRow( column(2,), column(5, box( title = "EV", width = 12, height = 80, style = "background-color: lightblue; border-color: #lightblue;", ) ), column(5,) ), fluidRow( column(2,), column(5,), column(1, textOutput("arrow2") ), column(4, box( title = "Trodelvy", width = 12, height = 80, style = "background-color: red; border-color: #red;", )) ) ) ) ) ) server <- function(input, output) {} shinyApp(ui, server)
可行解决方案
要给Shiny的Box组件添加连接线或箭头,有三种实用方案可选:
方案1:CSS伪元素绘制(适合固定简单布局)
给目标Box添加自定义ID,通过CSS的::before/::after伪元素结合绝对定位,直接绘制线条和箭头。这种方式无需额外依赖,适合布局固定的场景。
示例修改代码:
ui <- dashboardPage( dashboardHeader(title = "Connected Boxes"), dashboardSidebar(), dashboardBody( tags$style(HTML(" /* 给需要定位的Box设置相对定位 */ .connected-box { position: relative; } /* 绘制Bladder到EV的连接线+箭头 */ #bladder-box::after { content: ''; position: absolute; top: 50%; right: -180px; width: 180px; height: 2px; background-color: #333; transform: translateY(-50%); } #bladder-box::before { content: ''; position: absolute; top: 50%; right: -10px; transform: translateY(-50%); border: solid #333; border-width: 0 2px 2px 0; padding: 3px; transform: rotate(-45deg); } /* 可添加更多连接规则 */ ")), fluidRow( column(2, box( title = "Bladder", width = 12, height = 80, id = "bladder-box", class = "connected-box" ) ), # 其他Box添加对应id和connected-box类,比如EV的box设置id="ev-box" # ... 剩余原有代码 ) ) )
方案2:专业可视化包(适合复杂/交互式树状图)
如果布局复杂或需要交互式效果,推荐用visNetwork或DiagrammeR这类专业绘图包,将Box逻辑转换为节点-边关系,自动生成带连接的树状图。
示例(使用visNetwork):
library(shiny) library(shinydashboard) library(visNetwork) ui <- dashboardPage( dashboardHeader(title = "Connected Boxes"), dashboardSidebar(), dashboardBody( fluidRow( column(12, visNetworkOutput("tree_plot", height = "600px") ) ) ) ) server <- function(input, output) { output$tree_plot <- renderVisNetwork({ # 定义节点(对应原Box的内容和样式) nodes <- data.frame( id = 1:7, label = c("Bladder", "EV", "Trodelvy", "No ADC received", "No ADC received", "EV", "Trodelvy"), color = c("white", "lightblue", "red", "white", "white", "lightblue", "red") ) # 定义边(对应Box间的连接关系) edges <- data.frame( from = c(1,1,2,2,3,3), to = c(2,3,4,6,5,7), arrows = "to" ) # 生成可视化 visNetwork(nodes, edges) %>% visLayout(hierarchical = list(direction = "UD", sortMethod = "directed")) %>% visNodes(shape = "box", height = 80, width = 200) }) } shinyApp(ui, server)
方案3:SVG自定义绘制(适合高度自定义场景)
在页面中添加SVG容器,通过JS或Shiny的服务器端计算Box的位置坐标,动态绘制连接线。这种方式能实现最精准的自定义,但需要一定的前端知识。
内容的提问来源于stack exchange,提问作者firmo23
相关产品推荐
相关产品推荐

