g6解决拓扑图中dagre布局需要增加同级节点的问题(旁挂层同级节点相连)

背景:dagre可以在节点数据中配置layer字段,为节点指定层级,但layer的指定不能违背图结构与层次布局的原则,也就是说每一条边的起点的layer一定小于终点的layer值,否则会导致布局失败。

解决办法:动态添加节点,在需要增加同级节点的node处添加一个影子节点,隐藏该影子节点,将需要添加的节点动态添加到该影子节点上。

示例图:
在这里插入图片描述

代码如下:

import G6 from '@antv/g6';
import insertCss from 'insert-css';

insertCss(`
  .g6-tooltip {
    border-radius: 6px;
    font-size: 12px;
    color: #fff;
    background-color: #000;
    padding: 2px 8px;
    text-align: center;
  }
`);

const data = {
  nodes: [
    {
      id: '1',
      dataType: 'alps',
      name: '1',
      layer:0
    },
    {
      id: '2',
      dataType: 'alps',
      name: '2',
      layer:0
    },
    {
      id: '3',
      dataType: 'alps',
      name: '3',
      layer:1
    },
     {
      id: '6',
      dataType: 'sql2',
      name: '6',
      layer:3
    },
     {
      id: '7',
      dataType: 'sql2',
      name: '7',
      layer:3
    },
    
  ],
  edges: [
    {
      source: '2',
      target: '3',
    },
    {
      source: '1',
      target: '3',
    },
    {
      source: '3',
      target: '6',
    },
    {
      source: '3',
      target: '7',
    },

  ],
};

G6.registerNode(
  'sql',
  {
    drawShape(cfg, group) {
      const rect = group.addShape('rect', {
        attrs: {
          x: -75,
          y: -25,
          width: 150,
          height: 50,
          radius: 10,
          stroke: '#5B8FF9',
          fill: '#C6E5FF',
          lineWidth: 3,
        },
        name: 'rect-shape',
      });
      if (cfg.name) {
        group.addShape('text', {
          attrs: {
            text: cfg.name,
            x: 0,
            y: 0,
            fill: '#00287E',
            fontSize: 14,
            textAlign: 'center',
            textBaseline: 'middle',
            fontWeight: 'bold',
          },
          name: 'text-shape',
        });
      }
      return rect;
    },
  },
  'single-node',
);

const container = document.getElementById('container');
const width = container.scrollWidth;
const height = container.scrollHeight || 500;
const graph = new G6.Graph({
  container: 'container',
  width,
  height,
  layout: {
    type: 'dagre',
    ranksep: 70,
    controlPoints: true, 
  },
  defaultNode: {
    type: 'sql',
    size: [48, 48],
     anchorPoints: [
          // [0, 0],代表节点左上角的锚点,[1, 1],代表节点右下角的锚点。
          [0.5, 0], // 顶部中心锚点
          [0.5, 1], // 底部中心锚点
        ],
  },
  defaultEdge: {
    type: 'cubic-vertical',
    sourceAnchor: 1,
    style: {
      // radius: 20,
      // offset: 45,
      // endArrow: true,
      lineWidth: 1,
      stroke: '#C9CDD4',
      shadowBlur: 10,
    },
  },
  nodeStateStyles: {
    selected: {
      stroke: '#d9d9d9',
      fill: '#5394ef',
    },
  },
  modes: {
    default: [
      'drag-canvas',
      'zoom-canvas',
      'click-select',

    ],
  },
  fitView: true,
});
graph.data(data);
graph.render();
graph.on('afterrender',()=>{
  const targerNode = graph.findById('3');
  const realModel = targerNode.getModel();
  graph.addItem("node", {
      id: 'shadowNode',
      x: realModel.x,
      y: realModel.y,
      label: '影子节点',
      anchorPoints: [[0, 0.5], [1, 0.5]],
    });
  graph.findById('shadowNode').hide();
  graph.addItem("node", {
      id: 'add1',
      x: realModel.x + 200 + 20 * 3,
      y: realModel.y,
      label: '额外节点',
      anchorPoints: [[0.5, 0], [0.5, 0]]
    });
     graph.addItem("edge", {
      source: 'shadowNode',
      target: 'add1',
      type: 'arc',
    });
     graph.addItem("node", {
      id: 'add11',
      x: realModel.x + 400 + 20 * 3,
      y: realModel.y,
      label: '额外节点2',
      anchorPoints: [[0.5, 0], [0.5, 0]]
    });
    graph.addItem("edge", {
      source: 'shadowNode',
      target: 'add11',
      type: 'arc',
    });
})
if (typeof window !== 'undefined')
  window.onresize = () => {
    if (!graph || graph.get('destroyed')) return;
    if (!container || !container.scrollWidth || !container.scrollHeight) return;
    graph.changeSize(container.scrollWidth, container.scrollHeight);
  };

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式人工智能ESP32(4-PWM呼吸灯)

1、PWM基本原理 PWM(Pulse-width modulation)是脉冲宽度调制的缩写。脉冲宽度调制是一种模拟信号电平数字编码方法。脉冲宽度调制PWM是通过将有效的电信号分散成离散形式从而来降低电信号所传递的平均功率的一种方式。所以根据面积等效法则,…

超简单亿图图示安装教程/快速入门指南及快捷键大全

一、软件介绍 Edraw Max(亿图图示)作为一款全类型的图形图表设计软件,深受广大用户的欢迎。目前,Edraw Max(亿图图示)里拥有20000多个符号,有效地满足使用者的需求;另外,…

JDBC基础Demo

pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 …

STL六大组件

STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是C标准库的一部分&#xff0c;提供了丰富且高效的数据结构和算法。STL主要由6大组件构成&#xff0c;分别是容器、算法、迭代器、适配器、仿函数和空间配置器。 容器&#xff08;Containers&#…

ES6 (一)——ES6 简介及环境搭建

目录 简介 环境搭建 可以在 Node.js 环境中运行 ES6 webpack 入口 (entry) loader 插件 (plugins) 利用 webpack 搭建应用 gulp 如何使用&#xff1f; 简介 ES6&#xff0c; 全称 ECMAScript 6.0 &#xff0c;是 JavaScript 的下一个版本标准&#xff0c;2015.06 发版…

ICC2:insertion delay会拉长同一skew group其他sink吗?

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 来自知识星球提问: 已知一个skew group包含若干sink,针对其中一个sink设置insertion delay,希望工具把它做长,命令如下: create_clock_skew_group -clock xx -objects {xx xx} -name sg set_cl…

2024 江苏省第二届数据安全技术应用职业技能竞赛 初赛 部分wp

文章目录 一、前言二、参考文章三、题目&#xff08;解析&#xff09;数据安全解题赛1、ds_0602&#xff08;30分&#xff09;2、333.file&#xff08;45分&#xff09;3、pf文件分析&#xff08;35分&#xff09;4、丢失的资料&#xff08;45分&#xff09;5、greatphp&#x…

C#学习之路day2

一、变量 用来在存储计算机当中存储数据 1、常见的数据类型&#xff0c; 2、声明变量的方式 *声明&#xff1a;变量类型 变量名 &#xff1b; *赋值&#xff1a;变量名 值 &#xff1b; 先声明 &#xff0c;再赋值 &#xff0c;再使用 int num ; //声明num 10; //赋值i…

ArcGIS Pro 实现人口分布栅格TIFF数据的网格提取与可视化

这里在分享一个人口1km精度栅格数据&#xff0c;LandScan是由美国能源部橡树岭国家实验室&#xff08;ORNL&#xff09;提供的全球人口分布数据集&#xff0c;具有最高分辨率的全球人口分布数据&#xff0c;是全球人口数据发布的社会标准&#xff0c;是全球最为准确、可靠&…

React原理之Fiber双缓冲

前置文章&#xff1a; React原理之 React 整体架构解读React原理之整体渲染流程React原理之Fiber详解 -----读懂这一篇需要对 React 整体架构和渲染流程有大致的概念 &#x1f60a;----- 在前面的文章中&#xff0c;简单介绍了 Fiber 架构&#xff0c;也了解了 Fiber 节点的…

macOS安装搭建python环境

安装Homebrew apt-get是一个常见于Debian和Ubuntu等基于Linux的操作系统中的包管理工具&#xff0c;用于安装、更新和移除软件包。然而&#xff0c;macOS使用的是Homebrew或者MacPorts等其他的包管理工具&#xff0c;并不使用apt-get。 如果你想在macOS上使用类似apt-get的功…

书生大模型实战营-进阶关-Lagent 自定义你的 Agent 智能体

Lagent 自定义你的 Agent 智能体 Lagent 介绍环境配置Lagent Web体验第1步&#xff0c;启动大模型API服务第2步&#xff0c;启动 Lagent 的 Web页面 基于 Lagent 自定义智能体 Lagent 介绍 Lagent 是一个轻量级、开源的基于大语言模型的智能体&#xff08;agent&#xff09;框…

家里猫毛到处飞怎么办?如何清理?用宠物空气净化器去除猫毛

我家三只布偶原住民&#xff0c;都是掉毛怪&#xff0c;刚好还是不同的颜色&#xff0c;黑的灰的白的...家里和画板似的&#xff0c;每天都被猫毛上色&#xff0c;清扫时超级崩溃。沙发上、床上、地板上这些常见的地方就不用说了&#xff0c;甚至水杯和碗筷边偶尔也能看见猫毛&…

微服务的基本理解和使用

目录​​​​​​​ 一、微服务基础知识 1、系统架构的演变 &#xff08;1&#xff09;单体应用架构 &#xff08;2&#xff09;垂直应用架构 &#xff08;3&#xff09;分布式SOA架构 &#xff08;4&#xff09;微服务架构 &#xff08;5&#xff09;SOA与微服务的关系…

wincc报警如何通过短信发送给手机

单位使用WINCC上位机监控现场&#xff0c;需要把报警信息发送到指定手机上&#xff0c;能否实现&#xff1f;通过巨控GRMOPC系列远程智能控制终端&#xff0c;简单配置即可实现wincc报警短信传送到手机。配置过程无需任何通讯程序&#xff0c;也不要写任何触发脚本。 GRMOPC模…

Java中接口

接口的定义和使用 练习 public abstract class Animal {private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {this.name…

LIN通讯

目录 1 PLinApi.h 2 TLINFrameEntry 结构体 3 自定义函数getTLINFrameEntry 4 TLINScheduleSlot 结构体 5 自定义函数 getTLINScheduleSlot 6 自定义LIN_SetScheduleInit函数 7 自定义 LIN_StartSchedule 8 发送函数 9 线程接收函数 1 PLinApi.h 这是官方头文件 ///…

开源原型设计工具Penpot

Penpot是一个现代化、开源的协同设计平台&#xff0c;专为跨职能团队打造&#xff0c;提供了强大的在线设计和原型制作功能。 以下是对Penpot的详细介绍&#xff1a; 一、平台特点 开源与免费&#xff1a;Penpot是一个完全免费且开放源代码的项目&#xff0c;允许社区贡献和定…

20:【stm32】定时器一:时基单元

时基单元 1、什么是定时器2、时基单元的基本结构2.1&#xff1a;脉冲的来源2.2&#xff1a;预分频器PSC2.3&#xff1a;计数器CNT2.4&#xff1a;update事件与预加载 3、标准库编程3.1&#xff1a;通过定时器中断来设置延迟函数 1、什么是定时器 定时器是一种专门负责定时功能…

45.【C语言】指针(重难点)(H)

目录&#xff1a; 22.函数指针变量 *创建 *使用 *两段代码分析 23.函数指针数组 *基本用法 *作用 往期推荐 22.函数指针变量 *创建 类比数组指针变量的定义&#xff1a;存放数组地址的指针变量&#xff0c;同理函数指针变量存放函数的地址 格式 函数的返回类型 (*指针变量的…