Echarts-知识图谱

news/2024/5/19 23:10:30

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.mrgr.cn/p/66076863

相关文章

时序约束学习拓展(二):I/O约束笔记 + BUFIO IDDR协调方法

参考: https://cloud.tencent.com/developer/article/1652378 FPGA 静态时序分析与约束(1)_分析建立时间是否满足时序要求时要使用慢速模型;分析保持时间是否满足时序要求时-CSDN博客 放置失败问题: 在 Zynq7045 FPGA 中通过IDELAYE2驱动 BUFIO (xilinx.com)[Place 30-512]…

x86 64位的ubuntu环境下汇编(无优化)及函数调用栈的详解

1. 引言 为了深入理解c&#xff0c;决定学习一些简单的汇编语言。使用ubuntu系统下g很容易将一个c的文件编译成汇编语言。本文使用此方法&#xff0c;对一个简单的c文件编译成汇编语言进行理解。 2.示例 文件名&#xff1a;reorder_demo.cpp #include<stdio.h>typede…

aspnetcore插件开发dll热加载

该项目比较简单,只是单纯的把业务的dll模块和controller的dll做了一个动态的添加删除处理,目的就是插件开发。由于该项目过于简单,请勿吐槽。复杂的后续可以通过泛型的实体、dto等做业务和接口的动态区分。 项目结构如下: 上面的两个模块是独立通过dll加载道项目中的 rep…

Python浅谈清朝秋海棠叶版图

1、清朝疆域概述&#xff1a; 清朝是我国最后一个封建王朝&#xff0c;其始于1616年建州女真部努尔哈赤建立后金&#xff0c;此后统一女真各部、东北地区。后又降服漠南蒙古&#xff0c;1644年入关打败农民起义军、灭南明&#xff0c;削三藩&#xff0c;复台湾。后又收外蒙&am…

day07 51单片机-18B20温度检测

18B20温度检测 1.1 需求描述 本案例讲解如何从18B20传感器获取温度信息并显示在LCD上。 1.2 硬件设计 1.2.1 硬件原理图 1.2.3 18B20工作原理 可以看到18B20有两根引脚负责供电&#xff0c;一根引脚负责数据交换。18B20就是通过数据线和单片机进行数据交换的。 1&#xf…

zabbix监控安装文档

Zabbix安装部署文档https://blog.csdn.net/m0_56055257/article/details/131260948以上文档可以直接复制内容部署,写的非常好用在本教程中,展示如何在 CentOS 8 / RHEL 8 / Oracle Linux 8 / Alma Linux 8/ Rocky Linux 8 上安装最新的 Zabbix 6.4 版本。1、基本配置1.0关闭防…

ansible作业

ansible作业 0.ansible了解 roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例 roles/mysql/nginx/tomcat/redis/默认roles存放路径/root/.ansible/roles /usr/share/ansible/roles /etc/ansible/rolesroles目录结构: playbook1.yml…

使用composer开发自己的扩展包

前言 日常的开发中我们经常用到composer去安装其他人封装好的扩展包&#xff0c;如果你有好的功能代码想分享给其他人使用&#xff0c;就可以使用composer打包成扩展包。其他人用composer安装后就可以使用你的扩展包了。这篇文章教你如何打包自己的composer扩展包。 1.新建仓…

【JAVA】PO、VO、DAO、BO、DTO、POJO你分得清吗?

在Java开发中&#xff0c;PO、VO、DAO、BO、DTO、POJO这些词汇是比较常见的&#xff0c;每个术语都有其特定的含义和用途。下面是它们的具体区别&#xff1a; 名称简要概况用途和特定PO (Persistence Object) 持…

【汇编语言】直接定址表

【汇编语言】直接定址表 文章目录 【汇编语言】直接定址表前言一、移位指令移位指令过程逻辑移位指令shl 和 shr 二、操作显存数据显示的原理显示缓冲区的结构显示信息的一种“直接”方式 三、描述内存单元的标号关于标号去了冒号的数据标号数据标号同时描述内存地址和单元长度…

实验一———美团APP

墨刀、Axure、Mockplus等原型设计工具优缺点分析: 一、墨刀 优点:在轻量级的移动端原型制作更加迅速,展示更加方便。 缺点:价格较贵,不能画流程图,相对于其他两款功能还不是很全面;应用局限性,专注于app原型设计,在后台和网页稍有乏力;归档能力不足,更倾向于链接、二…

LLM学习(5)——系统评估与优化

5.1 如何评估 LLM 应用 5.1.1 验证评估的一般思路 通过不断寻找Bad Case并进行针对性优化,将这些案例逐步加入验证集,形成一个具有一定样本数量的验证集。针对这种验证集,逐个进行评估变得不切实际,需要一种自动评估方法来对整体性能进行评估。验证迭代是构建以LLM为核心的…

1张图片+3090显卡微调Qwen-VL视觉语言大模型(仅做演示、效果还需加大数据量)

原项目地址&#xff1a;https://github.com/QwenLM/Qwen-VL/blob/master/README_CN.md 环境本地部署&#xff08;见之前博文&#xff09; 【本地部署 】23.08 阿里Qwen-VL&#xff1a;能对图片理解、定位物体、读取文字的视觉语言模型 (推理最低12G显存) 一、数据集格式说明 …

ESLlint重大更新后,使用旧版ESLint搭配Prettier的配置方式

概要 就在前几天&#xff0c;ESLint迎来了一次重大更新&#xff0c;9.0.0版本&#xff0c;根据官方文档介绍&#xff0c;使用新版的先决条件是Node.js版本必须是18.18.0、20.9.0&#xff0c;或者是>21.1.0的版本&#xff0c;新版ESLint将不再直接支持以下旧版配置(非扁平化…

Modbus转Profinet网关连接LED大屏与PLC通讯

Modbus转Profinet网关(XD-MDPN100)的主要功能是实现Modbus协议和Profinet协议之间的转换和通信。Modbus转Profinet网关集成了Modbus和Profinet两种协议,支持Modbus RTU主站/从站,并可以与RS485接口的设备,如变频器、智能高低压电器、电量测量装置等进行连接。通过Modbus转…

【Go语言】接口类型(一)接口类型与接口的值

本文是介绍golang接口类型的第一篇&#xff0c;主要介绍接口类型与接口类型的值的相关概念。 1. 静态类型、动态类型、动态值 所谓的静态类型&#xff08;即 static type&#xff09;&#xff0c;就是变量声明的时候的类型。 var age int // int 是静态类型 var name strin…

2024年最好用的10款ER图神器!

分享10款ER图工具,详细分析他们的功能特点、价格和适用场景,可以根据你的需求进行选择。ER图(Entity-Relationship Diagram)是数据库设计中常用的一种模型,用于描述实体之间的关系。这种图形化的表示方法旨在帮助人们理解和设计数据库结构,它们在数据库开发和设计中非常有…

【Network Automation系列】-- 第二章

继续上文,【Network Automation系列】-- 第一章 在第1章,对TCP/IP协议套件和Python的回顾中,我们研究了网络通信协议背后的理论和规范。 我们还快速浏览了一下Python语言。在本章中,我们将开始深入研究使用Python对网络设备的管理。 特别是,我们将研究使用Python以编程方式…

初中中考阅读理解难题一网打尽!句子结构深度解析+答案揭秘,助你轻松冲刺高分!-012

PDF格式公众号回复关键字:ZKYDT012原文1 Richard found the bird in the forest, didn’t he? 解析 1 Richard ,found 发现了, the bird 这只鸟, in the forest 在森林里, didn’t he? 不是吗 理查德在森林里发现了这只鸟,不是吗? 2 He saw a strange bird in a bush. 他…

【51单片机项目】基于51单片机自制多功能小键盘/模拟USB键盘【附源码】(STC89C52RC+CH9328)

目录 一、效果展示 二、创作灵感 三、硬件电路 注意事项 工作原理 四、源码 main.c 五、附录 CH9328工作原理 CH9328的模式选择 ​编辑 全键盘键码值表 参考链接 一、效果展示 该小键盘具有三种功能&#xff1a; 1、自动输入开机密码 2、每隔一段时间自动按下ct…