Echarts-知识图谱

news2025/1/18 4:46:28

Echarts-知识图谱

demo地址

打开CodePen

效果

思路

1. 生成根节点
2. 根据子节点距离与根节点的角度关系,生成子节点坐标,进而生成子节点
3. 从子节点上按角度生成对应的子节点
4. 递归将根节点与每一层级子节点连线

核心代码

  • 定义节点配置
function getNodeConfig() {
  return {
    /** 节点间距 */
    nodeLine: 120,
    /** 节点大小 */
    nodeSize: 100,
    /** 子节点间距 */
    subNodeLine: 40,
    /** 子节点大小 */
    subNodeSize: 60
  };
}
  • 创建节点位置
function createNodePos({ index: i, len: iLen }) {
  const { nodeLine } = getNodeConfig();
  const radioDeg = (Math.PI * 2) / iLen;
  const deg = i * radioDeg + Math.PI / 4;
  const x = nodeLine * Math.cos(deg);
  const y = nodeLine * Math.sin(deg);

  const pos = { x, y };
  return pos;
}
  • 创建子节点位置
function createSubNodePos({ index: i, len: iLen }, { index: j, len: jLen }) {
  const { nodeLine, subNodeLine } = getNodeConfig();
  const radioDeg = (Math.PI * 2) / iLen;
  const deg = i * radioDeg + Math.PI / 4;
  const parentX = nodeLine * Math.cos(deg);
  const parentY = nodeLine * Math.sin(deg);

  const subRadioDeg = (Math.PI * 2) / (jLen + 1);
  const subDeg = j * subRadioDeg + (Math.PI / 2) * 3 + deg;
  const x = parentX + subNodeLine * Math.cos(subDeg);
  const y = parentY + subNodeLine * Math.sin(subDeg);

  const pos = { x, y };
  return pos;
}
  • 创建节点和链接
function initOption(root) {
  root.categoryItem = categories?.[root?.category] || {};
  const list = chartList || [];
  const graph = {
    ...createNodesLinks(list, root),
    categories
  };

  const chartOption = {
    color: categories?.map((item) => item?.color),
    legend: [
      {
        orient: 'vertical',
        left: 0,
        data: graph.categories.map(function (a) {
          return a.name;
        })
      }
    ],
    tooltip: {
      formatter: (params) => {
        return params?.data?.name;
      }
    },
    animationDuration: 1500,
    animationEasingUpdate: 'quinticInOut',
    series: [
      {
        type: 'graph',
        layout: 'none',
        force: {
          repulsion: 100
        },
        data: graph.nodes,
        links: graph.links,
        categories: graph.categories,
        roam: true,
        label: {
          show: true,
          width: 36,
          height: 36,
          overflow: 'breakAll',
          color: '#f2f2f2',
          formatter: (params) => {
            const { name = '', id } = params?.data || {};
            const len = id === rootId ? 20 : 10;
            return name?.length > len ? name?.slice(0, len) + '...' : name;
          }
        },
        lineStyle: {
          color: 'source',
          curveness: 0.3
        },
        emphasis: {
          focus: 'adjacency',
          disabled: true,
          lineStyle: {
            width: 10
          }
        }
      }
    ]
  };
  option = chartOption;
}

function createNodesLinks(list = [], root = {}) {
  const nodes = [];
  const links = [];
  const { nodeSize, subNodeSize } = getNodeConfig();

  nodes.push({
    id: rootId,
    category: 0,
    name: '根节点',
    ...root,
    symbolSize: nodeSize,
    x: 0,
    y: 0
  });

  for (let i = 0; i < list.length; i++) {
    const iIndex = String(i);
    const categoryItem = categories?.[i];
    nodes.push({
      id: iIndex,
      category: i,
      symbolSize: 1,
      label: {
        show: false
      },
      name: categoryItem?.name,
      ...createNodePos({ index: i, len: list.length })
    });
    links.push({
      source: rootId,
      target: iIndex
    });
    for (let j = 0; j < list[i].length; j++) {
      const jIndex = `${i}.${j}`;
      const jItem = _.get(list, jIndex, {});
      nodes.push({
        id: jIndex,
        category: i,
        symbolSize: subNodeSize,
        ...jItem,
        ...createSubNodePos({ index: i, len: list.length }, { index: j, len: list[i].length })
      });
      links.push({
        source: iIndex,
        target: jIndex
      });
    }
  }

  return { nodes, links };
};
  • 初始化
function init() {
  const { id, name, key } = { id: '1', name: '青霉素', key: 'drug-research' }
  const category = categories?.findIndex((item) => item?.key === key);
  const categoryItem = categories?.[category];
  initOption({
    category,
    dataId: id,
    name,
    id: rootId
  })
}

完整代码

var dom = document.getElementById('chart-container');
var myChart = echarts.init(dom, null, {
  renderer: 'canvas',
  useDirtyRect: false
});
var app = {};

var option;

const categories = [
    {
      name: '药物',
      color: 'rgba(0, 136, 184, 1)',
      key: 'drug-research',
      enumKey: 'Drug',
      fieldKey: 'drug',
      idKey: 'drug_uid',
      nameKey: 'drug_name_cn',
      nameEnKey: 'drug_name_en'
    },
    {
      name: '靶点',
      color: 'rgba(7, 214, 205, 1)',
      key: 'target-spot',
      enumKey: 'Target',
      fieldKey: 'target',
      idKey: 'target_uid',
      nameKey: 'target_name'
    },
    {
      name: '适应症',
      color: 'rgba(236, 153, 41, 1)',
      key: 'indications',
      enumKey: 'Indication',
      fieldKey: 'indication',
      idKey: 'indication_uid',
      nameKey: 'indication_name'
    },
    {
      name: '企业',
      color: 'rgba(210, 142, 200, 1)',
      key: 'company',
      enumKey: 'Entity',
      fieldKey: 'entity',
      idKey: 'entity_uid',
      nameKey: 'entity_name'
    },
    {
      name: '药物设计技术',
      color: 'rgba(255, 192, 185, 1)',
      key: 'drug-tech',
      enumKey: 'Tech',
      fieldKey: 'tech',
      idKey: 'tech_name',
      nameKey: 'tech_name'
    }
  ];

const rootId = 'root';
  
const serverMapData = {
  "drug": [
    {
      "drug_uid": "1",
      "drug_name_cn": "药物1",
      "drug_name_en": "药物en"
    },
    {
      "drug_uid": "2",
      "drug_name_cn": "药物2",
      "drug_name_en": "药物en"
    },
    {
      "drug_uid": "3",
      "drug_name_cn": "药物3",
      "drug_name_en": "药物en"
    },
    {
      "drug_uid": "4",
      "drug_name_cn": "药物4",
      "drug_name_en": "药物en"
    },
    {
      "drug_uid": "5",
      "drug_name_cn": "药物5",
      "drug_name_en": "药物en"
    },
  ],
  "target": [
    {
      "target_uid": "1",
      "target_name": "靶点1",
      "target_code": [
        "string"
      ]
    },
    {
      "target_uid": "2",
      "target_name": "靶点2",
      "target_code": [
        "string"
      ]
    },
    {
      "target_uid": "3",
      "target_name": "靶点3",
      "target_code": [
        "string"
      ]
    },
    {
      "target_uid": "4",
      "target_name": "靶点4",
      "target_code": [
        "string"
      ]
    },
    {
      "target_uid": "5",
      "target_name": "靶点5",
      "target_code": [
        "string"
      ]
    },
  ],
  "indication": [
    {
      "indication_uid": "1",
      "indication_name": "适应症1",
      "indication_code": [
        "string"
      ]
    },
    {
      "indication_uid": "2",
      "indication_name": "适应症2",
      "indication_code": [
        "string"
      ]
    },
    {
      "indication_uid": "3",
      "indication_name": "适应症3",
      "indication_code": [
        "string"
      ]
    },
    {
      "indication_uid": "4",
      "indication_name": "适应症4",
      "indication_code": [
        "string"
      ]
    },
    {
      "indication_uid": "5",
      "indication_name": "适应症5",
      "indication_code": [
        "string"
      ]
    },
  ],
  "entity": [
    {
      "entity_uid": "1",
      "entity_name": "企业1",
      "entity_code": [
        "string"
      ]
    },
    {
      "entity_uid": "2",
      "entity_name": "企业2",
      "entity_code": [
        "string"
      ]
    },
    {
      "entity_uid": "3",
      "entity_name": "企业3",
      "entity_code": [
        "string"
      ]
    },
    {
      "entity_uid": "4",
      "entity_name": "企业4",
      "entity_code": [
        "string"
      ]
    },
    {
      "entity_uid": "5",
      "entity_name": "企业5",
      "entity_code": [
        "string"
      ]
    },
  ],
  "tech": [
    {
      "tech_name": "技术1"
    },
    {
      "tech_name": "技术2"
    },
    {
      "tech_name": "技术3"
    },
    {
      "tech_name": "技术4"
    },
    {
      "tech_name": "技术5"
    },
  ]
}
  
const chartList = categories?.map((categoryItem) => {
  const dataList = serverMapData?.[categoryItem?.fieldKey] || [];
  return dataList?.map((item) => {
    return {
      ...item,
      categoryItem,
      dataId: item?.[categoryItem?.idKey],
      name: item?.[categoryItem?.nameKey] || item?.[categoryItem?.nameEnKey]
    };
  });
});

init();

function init() {
  const { id, name, key } = { id: '1', name: '青霉素', key: 'drug-research' }
  const category = categories?.findIndex((item) => item?.key === key);
  const categoryItem = categories?.[category];
  initOption({
    category,
    dataId: id,
    name,
    id: rootId
  })
}
  
function initOption(root) {
    root.categoryItem = categories?.[root?.category] || {};
    const list = chartList || [];
    const graph = {
      ...createNodesLinks(list, root),
      categories
    };

    const chartOption = {
      color: categories?.map((item) => item?.color),
      legend: [
        {
          orient: 'vertical',
          left: 0,
          data: graph.categories.map(function (a) {
            return a.name;
          })
        }
      ],
      tooltip: {
        formatter: (params) => {
          return params?.data?.name;
        }
      },
      animationDuration: 1500,
      animationEasingUpdate: 'quinticInOut',
      series: [
        {
          type: 'graph',
          layout: 'none',
          force: {
            repulsion: 100
          },
          data: graph.nodes,
          links: graph.links,
          categories: graph.categories,
          roam: true,
          label: {
            show: true,
            width: 36,
            height: 36,
            overflow: 'breakAll',
            color: '#f2f2f2',
            formatter: (params) => {
              const { name = '', id } = params?.data || {};
              const len = id === rootId ? 20 : 10;
              return name?.length > len ? name?.slice(0, len) + '...' : name;
            }
          },
          lineStyle: {
            color: 'source',
            curveness: 0.3
          },
          emphasis: {
            focus: 'adjacency',
            disabled: true,
            lineStyle: {
              width: 10
            }
          }
        }
      ]
    };
    console.log('chartOption', chartOption)
    option = chartOption;
  }

  function createNodesLinks(list = [], root = {}) {
    const nodes = [];
    const links = [];
    const { nodeSize, subNodeSize } = getNodeConfig();

    nodes.push({
      id: rootId,
      category: 0,
      name: '根节点',
      ...root,
      symbolSize: nodeSize,
      x: 0,
      y: 0
    });

    for (let i = 0; i < list.length; i++) {
      const iIndex = String(i);
      const categoryItem = categories?.[i];
      nodes.push({
        id: iIndex,
        category: i,
        symbolSize: 1,
        label: {
          show: false
        },
        name: categoryItem?.name,
        ...createNodePos({ index: i, len: list.length })
      });
      links.push({
        source: rootId,
        target: iIndex
      });
      for (let j = 0; j < list[i].length; j++) {
        const jIndex = `${i}.${j}`;
        const jItem = _.get(list, jIndex, {});
        nodes.push({
          id: jIndex,
          category: i,
          symbolSize: subNodeSize,
          ...jItem,
          ...createSubNodePos({ index: i, len: list.length }, { index: j, len: list[i].length })
        });
        links.push({
          source: iIndex,
          target: jIndex
        });
      }
    }

    return { nodes, links };
  };

  function getNodeConfig() {
    return {
      nodeLine: 120,
      nodeSize: 100,
      subNodeLine: 40,
      subNodeSize: 60
    };
  }

  function createNodePos({ index: i, len: iLen }) {
    const { nodeLine } = getNodeConfig();
    const radioDeg = (Math.PI * 2) / iLen;
    const deg = i * radioDeg + Math.PI / 4;
    const x = nodeLine * Math.cos(deg);
    const y = nodeLine * Math.sin(deg);

    const pos = { x, y };
    return pos;
  }

  function createSubNodePos({ index: i, len: iLen }, { index: j, len: jLen }) {
    const { nodeLine, subNodeLine } = getNodeConfig();
    const radioDeg = (Math.PI * 2) / iLen;
    const deg = i * radioDeg + Math.PI / 4;
    const parentX = nodeLine * Math.cos(deg);
    const parentY = nodeLine * Math.sin(deg);

    const subRadioDeg = (Math.PI * 2) / (jLen + 1);
    const subDeg = j * subRadioDeg + (Math.PI / 2) * 3 + deg;
    const x = parentX + subNodeLine * Math.cos(subDeg);
    const y = parentY + subNodeLine * Math.sin(subDeg);

    const pos = { x, y };
    return pos;
  }
  

if (option && typeof option === 'object') {
  myChart.setOption(option);
}

window.addEventListener('resize', myChart.resize);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1608455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将 Notepad++ 添加到右键菜单

目录 方式一&#xff1a;添加注册表&#xff08;手动&#xff09; 方式二&#xff1a;添加注册表&#xff08;一键添加&#xff09; 有时安装了notepad后&#xff0c;在txt文件上右键&#xff0c;在弹出的菜单栏中没有【通过 Notepad 打开】&#xff0c;如下&#xff1a; 这…

5. Django 探究CBV视图

5. 探究CBV视图 Web开发是一项无聊而且单调的工作, 特别是在视图功能编写方面更为显著. 为了减少这种痛苦, Django植入了视图类这一功能, 该功能封装了视图开发常用的代码, 无须编写大量代码即可快速完成数据视图的开发, 这种以类的形式实现响应与请求处理称为CBV(Class Base…

OSPF综合大实验

1、R4为ISP&#xff0c;其上只配置IP地址&#xff1b;R4与其他所直连设备间均使用公有IP&#xff1b; 2、R3-R5、R6、R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;除了R12有两个环回&#xff0c;其他路由器均有一个环…

Reka Core, Flash, and Edge: A Series of Powerful Multimodal Language Models

Reka Core, Flash, and Edge: A Series of Powerful Multimodal Language Models 相关链接&#xff1a;arxiv 关键字&#xff1a;Multimodal Language Models、Reka Core、Reka Flash、Reka Edge、State-of-the-Art 摘要 我们介绍了 Reka Core、Flash 和 Edge&#xff0c;这是…

VOJ islands打炉石传说 题解 二进制枚举

islands打炉石传说 代码 #include <bits/stdc.h> using namespace std; typedef long long ll; struct node {int cost, d, w; }; int main() {ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int n; // n张牌cin >> n;vector<node> v(n);for (int i 0; …

【深度学习实战(9)】三种保存和加载模型的方式

一、state_dict方式&#xff08;推荐&#xff09; torch.save(model.state_dict(), PATH)model YourModel() model.load_state_dict(torch.load(PATH)) model.eval()记住一定要使用model.eval()来固定dropout和归一化层&#xff0c;否则每次推理会生成不同的结果。 二、整个…

校园小情书微信小程序源码/社区小程序前后端开源/校园表白墙交友小程序

校园小情书前端代码&#xff0c;好玩的表白墙、树洞、校园论坛&#xff0c;可独立部署&#xff0c;也可以使用我部署的后台服务&#xff0c;毕业设计的好项目。 搭建教程&#xff1a; 一、注册管理后台 1、登录小情书站点进行注册&#xff1a;https://你的域名 2、注册成功…

Mathtype用法记录

常用写法 公式编号 给公式插入编号的方法 手动修改公式编号为指定值 例如编号(8.3.1)修改为(8.3.7)&#xff0c;即章、节号不变&#xff0c;公式序号改为7。 可修改编号的域代码&#xff0c;比如(8.3.1)的域代码为&#xff1a; { { MACROBUTTON MTPlaceRef \* MERGEFORMAT…

Redis 缓存预热、预热数据选取策略、缓存保温、性能边界

缓存预热 热点数据预热&#xff1a;根据业务分析或统计数据&#xff0c;确定热点数据&#xff08;经常被访问的数据&#xff09;&#xff0c;并将其提前加载到Redis缓存中。可以根据访问频率、访问量或其他业务指标来确定热点数据。定时预热&#xff1a;可以设置定时任务&…

Python兼职:只需要一台电脑宅在家,轻松实现月入过万!

Python兼职副业 Python是一种简单易学、高效强大的编程语言&#xff0c;正变成越来越多人选择的热门技能。不论你是否有编程基础&#xff0c;在学习Python的道路上&#xff0c;坚持每天投入2小时&#xff0c;你将看到巨大的回报。 学习Python不仅可以为你提供更多就业机会&am…

6.GodotCanvasItem、Node2D及自定义节点

CanvasItem节点 CanvasItem节点&#xff0c;CanvasItem -> Node&#xff0c;所以CanvasItem继承了Node的所有功能Canvas是画布的意思&#xff0c;所以CanvasItem代表了就是可以被绘制的节点&#xff0c;可以设置可视化界面和材质的颜色所有的2D节点和GUI节点都继承于CanvasI…

使用docker配置CCM-SLAM

一.Docker环境配置 1.拉取Docker镜像 sudo docker pull ubuntu:18.04拉取的为ununtu18版本镜像&#xff0c;环境十分干净&#xff0c;可以通过以下命令查看容器列表 sudo docker images 如果想删除多余的docker image&#xff0c;可以使用指令 sudo docker rmi -f <id&g…

openplc Linux 使用modbus RTU 从机通讯

1.Linux 环境下&#xff0c;openplc 默认使用的是modbus tcp协议通信。 想要使用串口 modbus rtu 通讯可以通过在runtime中添加SlaveDevices从机设备 2.添加设备&#xff0c;分配地址。 左边添加串口配置&#xff0c;右边是需要通讯的地址&#xff0c;从机地址都是从100开始&am…

了解光纤的最大损耗

在电信和数据传输领域&#xff0c;保持最佳的网络性能和可靠性至关重要。 影响网络完整性的关键因素之一是光纤中的信号丢失。信号损耗&#xff0c;也称为衰减损耗或光纤衰减&#xff0c;测量光缆输入和输出之间的光损耗量。本文将深入探讨光纤中的主要损耗&#xff0c;并指导您…

【python】计算水仙花数

【python】计算水仙花数 "水仙花数"是指一个3位数&#xff0c;它的三个位上的数字的3次幂之和等于它本身。例如&#xff0c;"153"就是一个水仙花数&#xff0c;因为1^3 5^3 3^3 153。以下是一个Python代码示例&#xff0c;用于计算并打印出所有的三位数…

抹机王的使用教程以及常见问题

首先请确保你已经正常安装了XPosed/EDXP/LSP框架并已激活抹机王模块&#xff0c;其中XP和EDXP模块均只需要框架内激活抹机王并重启即可&#xff0c;LSPosed注意作用域需要勾选上自己想要修改的APP&#xff08;如果你还是一意孤行只勾选系统框架那改机完全没用就是你自己的想法了…

性能测试-数据库优化二(SQL的优化、数据库拆表、分表分区,读写分离、redis、数据库监控)

数据库优化 explain select 重点&#xff1a; type类型&#xff0c;rows行数&#xff0c;extra SQL的优化 在写on语句时&#xff0c;将数据量小的表放左边&#xff0c;大表写右边where后面的条件尽可能用索引字段&#xff0c;复合索引时&#xff0c;最好按复合索引顺序写wh…

LeetCode 57—— 插入区间

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 第一步&#xff0c;我们先寻找新区间和原始区间列表的重叠部分。 假设新区间为 [ x 1 , x 2 ] [x_1, x_2] [x1​,x2​]&#xff0c;原始区间列表中的其中一个区间为 [ y 1 , y 2 ] [y_1, y_2] [y1​,y2​]&…

C++学习 <day1-C++介绍基础>

一、什么是C 1. C介绍 C由程序员控制生命周期&#xff08;性能提升&#xff09;&#xff1b;C数据存储等方式由硬件决定&#xff08;性能提升&#xff09;&#xff1b; C11 引入了 type_traits/range&#xff1b; C17 删除了 auto_ptr&#xff1b; 二、C开发环境&相关工…

数据库锁等待排查方法、命令行安装数据库及授权文件更新

欢迎关注“数据库运维之道”公众号&#xff0c;一起学习数据库技术! 本期将为大家分享“数据库锁等待排查方法、命令行安装数据库及授权文件更新”的运维技能。 关键词&#xff1a;锁等待、V$LOCK、V$TRXWAIT、死锁、锁超时、命令行部署达梦、授权文件更新 当用户反馈执行SQL语…