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

如何用R/JavaScript实现可折叠层级网络图并生成离线HTML

层级网络点击展开/双击折叠的离线可视化实现(R语言)

需求概述

  • 初始仅展示Boss节点
  • 单击节点展开其直接子节点
  • 双击节点折叠其已展开的子节点
  • 生成可离线打开的独立HTML文件,无需依赖Shiny应用

完整实现代码

library(igraph)
library(visNetwork)

# 构建TeamA数据
from_a <- c("Boss", "TeamA", "TeamA", "TeamA", "SubteamA1", "SubteamA1", "SubteamA1", 
            "SubteamA2", "SubteamA2", "SubteamA2", "SubteamA3", "SubteamA3", "SubteamA3")
to_a <- c("TeamA", "SubteamA1", "SubteamA2", "SubteamA3", "employee1", "employee2", "employee3", 
          "employee4", "employee5", "employee6", "employee7", "employee8", "employee9")
df_a <- data.frame(from = from_a, to = to_a)

# 构建TeamB数据
from_b <- c("Boss", "TeamB", "TeamB", "TeamB", "SubteamB1", "SubteamB1", "SubteamB1", 
            "SubteamB2", "SubteamB2", "SubteamB2", "SubteamB3", "SubteamB3", "SubteamB3")
to_b <- c("TeamB", "SubteamB1", "SubteamB2", "SubteamB3", "employee10", "employee11", "employee12", 
          "employee13", "employee14", "employee15", "employee16", "employee17", "employee18")
df_b <- data.frame(from = from_b, to = to_b)

# 合并数据
final_df <- rbind(df_a, df_b)

# 转换为有向igraph对象,便于识别父子关系
g <- graph_from_data_frame(final_df, directed = TRUE)
nodes <- data.frame(id = V(g)$name, label = V(g)$name)
edges <- as.data.frame(get.edgelist(g))
colnames(edges) <- c("from", "to")

# 给节点添加层级属性,初始隐藏非Boss节点
nodes$level <- sapply(nodes$id, function(x) {
  shortest.paths(g, v = "Boss", to = x)[1]
})
nodes$hidden <- nodes$id != "Boss"  # 初始仅显示Boss

# 自定义交互逻辑:点击展开子节点,双击折叠子节点
network <- visNetwork(nodes, edges) %>%
  visHierarchicalLayout(direction = "LR", levelSeparation = 200) %>%
  visInteraction(navigation = c("zoom", "drag")) %>%
  visEvents(
    click = "function(nodes) {
      if (nodes.nodes.length > 0) {
        var nodeId = nodes.nodes[0];
        // 筛选当前节点的直接子节点
        var children = edges.filter(function(e) { return e.from === nodeId; }).map(function(e) { return e.to; });
        // 显示子节点
        children.forEach(function(child) {
          network.body.data.nodes.update({id: child, hidden: false});
        });
      }
      return false;
    }",
    doubleClick = "function(nodes) {
      if (nodes.nodes.length > 0) {
        var nodeId = nodes.nodes[0];
        // 筛选当前节点的直接子节点
        var children = edges.filter(function(e) { return e.from === nodeId; }).map(function(e) { return e.to; });
        // 隐藏子节点
        children.forEach(function(child) {
          network.body.data.nodes.update({id: child, hidden: true});
        });
      }
      return false;
    }"
  )

# 导出为离线HTML文件
visSave(network, file = "hierarchical_network.html")

代码说明

  1. 数据整理:修正原代码中重复赋值的问题,分别创建两个团队的边数据后合并,转换为有向igraph对象以明确父子节点关系。
  2. 节点预处理:
    • 计算每个节点与Boss的最短路径作为层级标记
    • 设置初始隐藏非Boss节点,实现仅展示根节点的初始状态
  3. 交互逻辑:
    • 通过visEvents绑定点击和双击事件,用JavaScript筛选当前节点的直接子节点
    • 点击时将子节点的hidden属性设为false实现展开,双击时设为true实现折叠
  4. 布局与导出:使用横向层级布局优化展示效果,通过visSave直接生成可离线打开的HTML文件,无需额外依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 18:11:09