Vue+G6搭建力导向图

news2024/11/16 1:38:49

1 效果

在这里插入图片描述
初始化时节点向中间聚拢
拖动后,随引力作用缓缓向中间聚拢
点击节点,节点放大,并展示标签文字

2 代码分析

2.1 数据

2.1.1 节点数据

nodes: [
          {
            id: '0',
            label: '0',
            value: 10,
            cluster: 'a',
            description: 'this is node 0, \nand the value of it is 10',
          },
          {
            id: '1',
            label: '1',
            value: 20,
            cluster: 'b',
            description: 'this is node 1, \nand the value of it is 20',
          },

value: 决定节点大小
cluster: a b c d 对应不同的样式 cluster值决定拿到colors、strokes数组中的某一项
label: 默认节点文本(默认配置项属性)
description: 点击节点放大后 该该数据赋值给label 展示文本

2.1.2 节点样式

样式并不是按照顺序固定给某节点的的,而是通过cluster拿到对应数组的某一项,赋予节点

	  // 节点填充颜色
      const colors = [
        '#BDD2FD',
        '#BDEFDB',
        '#C2C8D5',
        '#FBE5A2',
        '#F6C3B7',
        '#B6E3F5',
        '#D3C6EA',
        '#FFD8B8',
        '#AAD8D8',
        '#FFD6E7',
      ];
      // 节点边颜色
      const strokes = [
        '#5B8FF9',
        '#5AD8A6',
        '#5D7092',
        '#F6BD16',
        '#E8684A',
        '#6DC8EC',
        '#9270CA',
        '#FF9D4D',
        '#269A99',
        '#FF99C3',
      ];

2.2 图配置

Graph 的初始化通过 new 进行实例化,实例化时需要传入需要的参数。

<div id="container"></div>

const graph = new G6.Graph({
        container: 'container',
        width,
        height,
        layout: {
          type: 'force', // 力导向布局
          nodeStrength: 30, // 节点作用力,正数代表节点之间的引力作用,负数代表节点之间的斥力作用
          collideStrength: 0.7, // 防止重叠的力强度,范围 [0, 1]
          alphaDecay: 0.01, // 迭代阈值的衰减率 ?啥玩意
          preventOverlap: true, // 是否防止重叠 必须在数据中设置了 size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值
        },
        modes: {
          default: ['collapse-expand-combo'], // combo类型 之前采用drag-node 不太丝滑
        },
        defaultNode: {
          size: [10, 10],
        },
      });

2.3 定义节点样式

// 遍历nodes 根据cluster属性 给节点添加对应style属性
      nodes.forEach((node) => {
        nodeMap.set(node.id, node);
        // cluster
        if (node.cluster && clusterMap.get(node.cluster) === undefined) {
          clusterMap.set(node.cluster, clusterId);
          clusterId++;
        }
        const cid = clusterMap.get(node.cluster);
        if (!node.style) node.style = {};
        node.style.fill = colors[cid % colors.length]; //节点颜色
        node.style.stroke = strokes[cid % strokes.length]; //节点边颜色
        node.x = width / 2 + 200 * (Math.random() - 0.5);
        node.y = height / 2 + 200 * (Math.random() - 0.5);
      });

2.4 节点大小设置

// 调用scaleNodeProp
scaleNodeProp(nodes, 'size', 'value', nodeSizeDataRange, nodeSizeRange);

      // 添加size属性
      function scaleNodeProp (elements, propName, refPropName, dataRange, outRange) {
        const outLength = outRange[1] - outRange[0];
        const dataLength = dataRange[1] - dataRange[0];
        elements.forEach(function (n) {
          if (propName.split('.')[0] === 'style') {
            if (n.style) {
              n.style[propName.split('.')[1]] =
                ((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0];
            } else {
              n.style = _defineProperty(
                {},
                propName.split('.')[1],
                ((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0],
              );
            }
          } else {
            n[propName] = ((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0];
          }
        });
      }

2.5 节点交互事件

  // 方法:跟随拖动的位置 节点位置移动
  // 参数e:鼠标拖动信息
  function refreshDragedNodePosition (e) {
    const model = e.item.get('model');
    model.fx = e.x;
    model.fy = e.y;
  }

2.5.1 节点开始被拖拽

  // 事件绑定 graph.on()
  // Node 交互事件: node:dragstart 当节点开始被拖拽的时候触发的事件
  graph.on('node:dragstart', function (e) {
    graph.layout(); // graph.layout()重新以当前配置的属性进行一次布局
    refreshDragedNodePosition(e);
  });

2.5.2 开始拖拽过程

  // node:drag  当节点在拖动过程中时触发的事件
  graph.on('node:drag', function (e) {
    refreshDragedNodePosition(e);
  });

2.5.3 拖拽完成后

  // node:dragend 当拖拽完成后触发的事件
  graph.on('node:dragend', function (e) {
    e.item.get('model').fx = null;
    e.item.get('model').fy = null;
  });

2.5.4 点击事件

  // node:click 鼠标左键单击节点时触发
  graph.on('node:click', function (e) {
    // debugger;
    const node = e.item; //那到当前点击的节点
    const states = node.getStates(); //返回当前元素的所有状态 啥也没有
    let clicked = false;
    const model = node.getModel(); // 获得节点位置
    let size = 200; // 变大
    let labelText = 'NODE: ' + model.id + '\n' + model.description; // 拼接: "NODE:  this is node 8, and the value of it is 21"
    states.forEach(function (state) {
      if (state === 'click') {
        clicked = true;
        size = model.oriSize;
        labelText = model.oriLabel;
      }
    });
    graph.setItemState(node, 'click', !clicked); //设置元素状态(元素实例,状态值,是否启用状态)
    // 更新元素,包括更新数据、样式等
    graph.updateItem(node, {
      size,
      label: labelText,
    });
    graph.layout(); // graph.layout()重新以当前配置的属性进行一次布局
  });

2.6 初始化图数据

  graph.data(data); // 初始化图数据,data是一个包括 节点 数组和 边 数组的对象
  graph.render();

2.7 mounted() 调用

上述代码包裹在 getInit() 方法中
在组件挂载后调用 getInit()

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

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

相关文章

帆软数据填报——多字段联合校验数据是否重复

功能&#xff1a;同一张表中&#xff0c;在填报时&#xff0c;设定多个字段联合维度下&#xff0c;记录不允许出现2条及以上 EG&#xff1a;同个项目同个时间维度不允许存在2条及以上的记录 效果&#xff1a; 说明&#xff1a;如果设定“管理项目编码”和“统计截止日期”字段…

【树莓派】解密树莓派Python项目中神秘的导入错误

文章目录 问题导入python文件目录分析解决方案 问题导入 小编在使用树莓派编写python项目时出现了以下两种错误&#xff1a; ModuleNotFoundError : No module named Motor from ..hardware.motor import Motor portError: attempted relative import with no known parent p…

【C语言】手把手带你解决青蛙跳台阶问题

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,这里是君兮_&#xff0c;今天更新的是经典递归问题——青蛙跳台阶&#xff0c;在所有有关递归的问题中&#xff0c;青蛙跳台阶是最广为人知的问题之一&#xff0c;可以说&#xff0c;如果你能真正弄懂青蛙跳台阶问…

javaweb学习2

p标签使用 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!--p标签定义段落 p元素自动在其前后创建一段空白--> hello&#xff0c;world &l…

电脑鼠标怎么改变形状

电脑鼠标怎么改变形状? 首先你要下载一个鼠标指针包&#xff0c;网上有很多这样的资源&#xff0c;选择你喜欢的那一个指针包。 点击开始菜单&#xff0c;找到控制面板&#xff0c;打开控制面板。 从控制面板里点击“硬件和声音”&#xff0c;在设备和打印机里面点击“鼠标”。…

1-Eureka服务注册与发现以及Eureka集群搭建(实操型)

1-Eureka服务注册与发现以及Eureka集群搭建&#xff08;实操型&#xff09; 1. 简单搭建微服务框架1.1 idea创建maven多模块项目1.2 项目结构1.3 项目依赖与配置1.3.1 父工程&#xff1a;dog-cloud-parent1.3.2 管理实体项目&#xff1a;dog-po1.3.3 服务提供者&#xff1a;dog…

HBase(9):过滤器

1 简介 在HBase中,如果要对海量的数据来进行查询,此时基本的操作是比较无力的。此时,需要借助HBase中的高级语法——Filter来进行查询。Filter可以根据列簇、列、版本等条件来对数据进行过滤查询。因为在HBase中,主键、列、版本都是有序存储的,所以借助Filter,可以高效地…

主流开源深度学习框架简介

主流开源深度学习框架简介 本文目录&#xff1a; 一、TensorFlow深度学习框架 二、PyTorch深度学习框架 三、Keras深度学习框架 四、Caffe深度学习框架 五、中国深度学习开源框架状况 六、几种框架的对比 七、其他统计数据 当下&#xff0c;有许多主流的开源深度学习框架…

mysql 模糊查询的字段 支持不区分大小写功能

1. 直接修改字段对应的校对规则即可 ​​​​​​ 2. 校对规则说明 ​ utf8_bin 将字符串中的每一个字符用二进制数据存储&#xff0c;区分大小写。 utf8_genera_ci 不区分大小写&#xff0c;ci为case insensitive的缩写&#xff0c;即大小写不敏感。utf8_general_cs 区分…

香蕉派BPI-R4 Wifi7路由器采用联发科MT7988A (Filogic 880)设计

香蕉派BPI-R4路由器板采用联发科MT7988A (Filogic 880)四核ARM Corex-A73方案设计&#xff0c;板载4GB DDR4内存,8GB eMMC存储,128MB SPI-NAND闪存&#xff0c;还具有2个10Gbe SFP光电口, 4x Gbe千兆网口&#xff0c;带USB3.2端口&#xff0c;M.2接口支持4G/5G/NVME SSD.2x min…

海外版“咸鱼”Carousell是什么?

做跨境的都知道&#xff0c;一定不能只在一颗树上吊死&#xff0c;潮流总是把你推着向前的&#xff0c;现在跨境电商平台一样层出不穷。今天就来跟大家分享最近发现比价好做的外贸电商平台APP——Carousell。号称海外版“咸鱼”&#xff0c;它的功能也与咸鱼是差不多的&#xf…

群晖ssh登录并开启root用户登录功能

说明 群辉默认不允许SSH使用ROOT远程登陆&#xff0c;只能用手动创建的账户登陆&#xff0c;需要拷贝破解文件的时候会提示权限不足&#xff0c;这个时候肯定需要通过root用户去登录靠北 启动ssh登录功能 双击控制面板 点击终端和SNMP 启用ssh和telnet 点击应用 finalshel…

SpringBoot入门:使用IDEA构建第一个SpringBoot项目

SpringBoot框架介绍 Spring Boot是一个简化Spring开发的框架&#xff0c;用来监护spring应用开发&#xff0c;约定大于配置&#xff0c;去繁就简&#xff0c;just run 就能创建一个独立的&#xff0c;产品级的应用。我们在使用Spring Boot时只需要配置相应的Spring Boot就可以…

编译原理三:词法分析

概念 在编译器工作流程中&#xff0c;词法分析是将源代码分解为一系列词法单元的过程。 词法单元包括标识符、关键字、运算符等。词法分析器会读取源代码的每一个字符&#xff0c;根据预定义的规则将它们组成一系列词法单元。 词法分析器通常使用有限状态机来实现。有限状态机…

如何解决在vue3+vite项目中加载不了.tga文件的问题

因项目需求所以需要加载 .tga 类型的文件 import backgroundImage from "/assets/combined_image.tga" import { TGALoader } from "three/addons/loaders/TGALoader.js";const loader new TGALoader(); const texture1 loader.load(backgroundImage);但…

操作系统5:线程的概念和线程实现

目录 1、线程的概念 &#xff08;1&#xff09;进程和进程并发是所需要付出的时空开销 &#xff08;2&#xff09;线程和进程的比较 &#xff08;3&#xff09;线程的状态和线程的控制块 2、线程的实现 &#xff08;1&#xff09;线程的实现方式 &#xff08;2&#xff…

2.编程语言的代码规则和规范

**格式和规范**只需要记住最原始的c和c的语言规则就可以了不要把所有的方法都掌握了 比如孔乙己 每个语法之间要有空格或分隔符 2。“”英文双引号里面是不需要的&#xff0c;这个双引号里面输入什么都可以 3.预处理的命令 必须一条占一行

传统美业如何拓客引流?如何借力小程序实现低成本引流与锁客

​传统门店的经营方式主要靠广告投入和口碑传播&#xff0c;然而&#xff0c;门店客流寥寥无几&#xff0c;如今&#xff0c;移动互联网时代&#xff0c;新零售的盛行&#xff0c;传统实体门店急需转型&#xff0c;接轨新的商业营销模式来为门店引流。 处在小程序爆发的风口&a…

《PyTorch深度学习实践》第四讲 反向传播

b站刘二大人《PyTorch深度学习实践》课程第四讲反向传播笔记与代码&#xff1a;https://www.bilibili.com/video/BV1Y7411d7Ys?p4&vd_sourceb17f113d28933824d753a0915d5e3a90 对于上述简单的模型可以用解析式来做&#xff0c;但是对于复杂模型而言&#xff0c;如下图每个…

详解线程池的作用和实际应用以及拒绝策略

目录 线程池的作用&#xff1f; 线程池的意义&#xff1a; 线程池的参数 ​编辑 线程池任务执行的顺序 线程池拒绝策略 四种策略 应用场景分析 AbortPolicy DiscardPolicy DiscardOldestPolicy CallerRunsPolicy 线程池的作用&#xff1f; 优化系统架构通常包括在时间…