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

如何在Apache ECharts关系图中实现分类筛选并隐藏无关联节点?

需求实现方案

这个需求完全可以实现,核心是通过监听分类选择操作,动态筛选出选中分类下存在关联链接的节点及对应链接,再更新ECharts配置来刷新图表。以下是具体修改步骤和代码调整:

1. 添加顶部分类选择控件

在页面顶部(<div id="container">之前)添加分类选择下拉框,用于触发分类筛选:

<div style="padding: 10px; background: #f5f5f5;">
  <label>选择分类:</label>
  <select id="categorySelect">
    <option value="all">全部分类</option>
    <!-- 选项将通过JS动态生成 -->
  </select>
</div>

2. 保存原始数据,避免重复请求

获取JSON数据后,将原始的节点、链接和分类数据保存到全局变量,方便切换分类时复用:

// 在getJSON回调内部保存原始数据
window.rawGraphData = {
  nodes: [...graph.nodes],
  links: [...graph.links],
  categories: [...graph.categories]
};

同时动态生成下拉框的分类选项:

// 生成分类选择项
const select = document.getElementById('categorySelect');
graph.categories.forEach(cat => {
  const option = document.createElement('option');
  option.value = cat.name;
  option.textContent = cat.name;
  select.appendChild(option);
});

3. 添加分类筛选与图表更新逻辑

编写筛选函数,根据选中分类过滤出关联节点和链接,再更新图表:

// 分类筛选函数
function filterGraphByCategory(categoryName) {
  let filteredNodes = [...window.rawGraphData.nodes];
  let filteredLinks = [...window.rawGraphData.links];

  if (categoryName !== 'all') {
    // 获取选中分类的ID
    const targetCategoryId = window.rawGraphData.categories.find(c => c.name === categoryName).id;
    // 找出该分类下的所有节点ID
    const targetNodeIds = window.rawGraphData.nodes.filter(node => node.category === targetCategoryId).map(node => node.id);
    
    // 筛选出与目标节点有关联的链接
    const relatedLinks = window.rawGraphData.links.filter(link => {
      // 兼容links中source/target为对象或ID值的情况
      const sourceId = typeof link.source === 'object' ? link.source.id : link.source;
      const targetId = typeof link.target === 'object' ? link.target.id : link.target;
      return targetNodeIds.includes(sourceId) || targetNodeIds.includes(targetId);
    });
    
    // 收集所有关联节点的ID
    const relatedNodeIds = new Set();
    relatedLinks.forEach(link => {
      const sourceId = typeof link.source === 'object' ? link.source.id : link.source;
      const targetId = typeof link.target === 'object' ? link.target.id : link.target;
      relatedNodeIds.add(sourceId);
      relatedNodeIds.add(targetId);
    });
    
    // 最终筛选出关联节点
    filteredNodes = window.rawGraphData.nodes.filter(node => relatedNodeIds.has(node.id));
    filteredLinks = relatedLinks;
  }

  // 更新图表配置
  myChart.setOption({
    series: [{
      data: filteredNodes,
      links: filteredLinks
    }]
  });
}

// 绑定分类选择事件
document.getElementById('categorySelect').addEventListener('change', function(e) {
  filterGraphByCategory(e.target.value);
});

完整修改后的代码

整合所有修改后的完整代码如下:

<!--
    Knowledge Map v2
-->
<!DOCTYPE html>
<html lang="en" style="height: 100%">
<head>
  <meta charset="utf-8">
</head>
<body style="height: 100%; margin: 0">
  <!-- 添加分类选择控件 -->
  <div style="padding: 10px; background: #f5f5f5;">
    <label>选择分类:</label>
    <select id="categorySelect">
      <option value="all">全部分类</option>
    </select>
  </div>

  <div id="container" style="height: 100%"></div>

  <script type="text/javascript" src="jquery.min.js"></script>
  <script type="text/javascript" src="echarts.min.js"></script>

  <script type="text/javascript">
    var dom = document.getElementById('container');
    var myChart = echarts.init(dom, null, {
      renderer: 'canvas',
      useDirtyRect: false
    });
    var app = {};
    var ROOT_PATH = '';
    var option;

    myChart.showLoading();
$.getJSON(ROOT_PATH + '/Graph_Data/KnowledgeMapData.json', function (graph) {
  myChart.hideLoading();

  // 保存原始数据
  window.rawGraphData = {
    nodes: [...graph.nodes],
    links: [...graph.links],
    categories: [...graph.categories]
  };

  // 生成分类选择选项
  const select = document.getElementById('categorySelect');
  graph.categories.forEach(cat => {
    const option = document.createElement('option');
    option.value = cat.name;
    option.textContent = cat.name;
    select.appendChild(option);
  });

  option = {
    tooltip: {},
    legend: [
      {
        data: graph.categories.map(function (a) {
          return a.name;
        })
      }
    ],
    series: [
      {
        name: 'Aranea Knowledge Map',
        type: 'graph',
        layout: 'none',
        data: graph.nodes,
        links: graph.links,
        categories: graph.categories,
        roam: true,
        label: {
          show: true,
          position: 'right',
          formatter: '{b}'
        },
        labelLayout: {
          hideOverlap: true
        },
        scaleLimit: {
          min: 0.4,
          max: 2
        },
        lineStyle: {
          color: 'source',
          curveness: 0.1
        }
      }
    ]
  };
  myChart.setOption(option);

  // 分类筛选函数
  function filterGraphByCategory(categoryName) {
    let filteredNodes = [...window.rawGraphData.nodes];
    let filteredLinks = [...window.rawGraphData.links];

    if (categoryName !== 'all') {
      const targetCategoryId = window.rawGraphData.categories.find(c => c.name === categoryName).id;
      const targetNodeIds = window.rawGraphData.nodes.filter(node => node.category === targetCategoryId).map(node => node.id);
      
      const relatedLinks = window.rawGraphData.links.filter(link => {
        const sourceId = typeof link.source === 'object' ? link.source.id : link.source;
        const targetId = typeof link.target === 'object' ? link.target.id : link.target;
        return targetNodeIds.includes(sourceId) || targetNodeIds.includes(targetId);
      });
      
      const relatedNodeIds = new Set();
      relatedLinks.forEach(link => {
        const sourceId = typeof link.source === 'object' ? link.source.id : link.source;
        const targetId = typeof link.target === 'object' ? link.target.id : link.target;
        relatedNodeIds.add(sourceId);
        relatedNodeIds.add(targetId);
      });
      
      filteredNodes = window.rawGraphData.nodes.filter(node => relatedNodeIds.has(node.id));
      filteredLinks = relatedLinks;
    }

    myChart.setOption({
      series: [{
        data: filteredNodes,
        links: filteredLinks
      }]
    });
  }

  // 绑定分类选择事件
  document.getElementById('categorySelect').addEventListener('change', function(e) {
    filterGraphByCategory(e.target.value);
  });
});

    window.addEventListener('resize', myChart.resize);
  </script>
</body>
</html>

注意事项

  • 代码兼容了links中source/target为节点对象或ID值的两种情况,适配不同的数据格式。
  • 原始数据通过全局变量存储,确保每次切换分类都能从完整数据集中重新筛选,避免数据丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:53:17