Giter Club home page Giter Club logo

g6's Introduction

English | 简体中文

G6: A Graph Visualization Framework in TypeScript

npm Version Build Status Coverage Status npm Download typescript npm License

IntroductionExamplesQuick StartAPI

G6 is a graph visualization engine. It provides basic capabilities for graph visualization and analysis such as drawing, layout, analysis, interaction, animation, themes, and plugins. With G6, users can quickly build their own graph visualization and analysis applications, making relational data simple, transparent, and meaningful.

✨ Features

G6, as a professional graph visualization engine, boasts the following features:

  • Rich Elements: It comes with a variety of built-in node, edge, and Combo UI elements with extensive style configurations, supports data callbacks, and has a flexible mechanism for extending custom elements.
  • Controllable Interactions: It includes more than 10 built-in interaction behaviors and offers a rich array of events, facilitating the expansion of custom interactive behaviors.
  • High-Performance Layout: The engine features more than 10 common graph layouts, some of which leverage GPU and Rust parallel computing for enhanced performance, and it supports custom layout development.
  • Convenient Plugins: Optimized built-in plugin functionality and performance, with flexible extensibility, making it easier to implement customized business capabilities.
  • Multiple Theme and Palettes: Provides two sets of built-in themes, light and dark, that integrate over 20 popular community color palettes based on the AntV new color scheme.
  • Multi-Environment Rendering: Harnessing the power of G, it supports rendering in Canvas, SVG, and WebGL, as well as server-side rendering with Node.js; it also offers plugin packages that provide powerful 3D rendering and spatial interactions based on WebGL.
  • React Ecosystem: By utilizing the React front-end ecosystem, it supports React nodes, significantly enriching the presentational styles of G6 nodes.

🔨 Getting Started

G6 is usually installed via a package manager such as npm or Yarn.

$ npm install @antv/g6

The Graph object then can be imported from G6.

<div id="container"></div>
import { Graph } from '@antv/g6';

// Get the Data.
const data = {
  nodes: [
    /* your nodes data */
  ],
  edges: [
    /* your edges data */
  ],
};

// Create the Graph instance.
const graph = new Graph({
  container: 'container',
  data,
  node: {
    palette: {
      type: 'group',
      field: 'cluster',
    },
  },
  layout: {
    type: 'force',
  },
  behaviors: ['drag-canvas', 'drag-node'],
});

// Render the Graph.
graph.render();

All goes well, you can get the following lovely graph!

🌍 Ecosystem

  • Ant Design Charts: A React chart library based on G2, G6, X6, L7.
  • Graphin: A simple React wrapper based on G6, as well as an SDK for developing graph visualization applications.

For more ecosystem open-source projects, contributions are welcome. Please feel free to submit a PR for inclusion.

📮 Contributing

  • Issue Reporting: If you encounter any issues with G6 during use, please feel free to submit an issue, along with the minimal sample code that can reproduce the problem.
  • Contribution Guide: Information on how to get involved in the development and contribution to G6.
  • Ideas Discussion: Discuss your ideas on GitHub Discussions or in the DingTalk group.

📄 License

MIT.

g6's People

Contributors

yanyan-wang avatar elaine1234 avatar aarebecca avatar yvonneyx avatar pomelo-nwu avatar tomhuangcn avatar mxz96102 avatar chenluli avatar openwayne avatar hustcc avatar albertaz1992 avatar afc163 avatar zxc0328 avatar xiaoiver avatar zqqcee avatar bzhangzju avatar colinchen2 avatar k644606347 avatar ai-qing-hai avatar lxfu1 avatar fisherllcy avatar deturium avatar spengjie avatar dependabot-preview[bot] avatar songhn233 avatar vellengs avatar liaodalin19903 avatar zhanba avatar wunaidage avatar chenpeng-yiyu avatar

Stargazers

 avatar  avatar 黄小健 avatar  avatar Pl7y avatar  avatar Ahn TaeGyu avatar 阿灿在吗 avatar  avatar Kostas avatar Muhammad Hadi avatar Dylan avatar  avatar 织蛾 avatar Hung Hoang avatar Anonymous avatar Nolan avatar  avatar  avatar superBiuBiu avatar msleek avatar 时序图谱洞察引擎 avatar Ivo avatar liuzhide avatar  avatar Rui Zhang avatar  avatar  avatar Yong Liang avatar  avatar XiaoyuWang avatar zhangr4 avatar Felipe Vallejo avatar Guillaume Grossetie avatar  avatar OnePeople avatar  avatar ScuTua avatar  avatar Oleg Veselkov avatar huhongfei avatar  avatar huiyu.zjt avatar Benny avatar zhou kai avatar  avatar  avatar Fabrice Boyer avatar qinxing avatar One avatar huangyong avatar Rosemary Macejkovic avatar miaoyc avatar Marcus Feitoza avatar Srijan Chaudhary avatar  avatar Freddy Ma avatar  avatar Fahimul Hoque avatar  avatar Galvagno Sébastien avatar  avatar Oğuzhan avatar Cookie avatar  avatar warriorHj avatar  avatar 洛晓春 avatar  avatar XinyueDu avatar xiaojie.zj avatar Tim O'Guin avatar GooseCMD avatar bai0012 avatar  avatar  avatar  avatar Zack avatar oldwenzi avatar meta avatar 宁培培 avatar  avatar  avatar Dust Free avatar  avatar  avatar Jasonking avatar 光头强又来砍树了 avatar  avatar Will Yu avatar luct avatar Aze avatar zhoulixiang avatar 二进制 avatar nfym avatar  avatar Hazel avatar Fanny avatar Somasree Majumder avatar MaWei avatar

Watchers

mlzboy avatar Ubao Daddy avatar Army avatar  avatar LiYaFeng avatar  avatar greysun avatar 木家彤 avatar  Justin chen avatar  avatar  avatar  avatar duansm avatar Arthur.Ren avatar  avatar  avatar  avatar timelyportfolio avatar James Cloos avatar Easter avatar aurimas avatar  avatar 郑萧001 avatar diycp avatar akbarwibawa avatar zhangaz1 avatar Gargool avatar dong avatar luyu avatar  avatar Samir avatar 胡继伟 avatar Yuri Kachanyuk avatar  avatar  avatar Edward Xie avatar Emmanuel Lazarte avatar  avatar 蔡正海 avatar Adam avatar  avatar CaiCai avatar  avatar  avatar  avatar  avatar DapengLi avatar  avatar  avatar  avatar Zhanliang Liu avatar  avatar  avatar scaletimes avatar  avatar Cao sg avatar crny avatar harry avatar Lei.yang avatar ghj1976 avatar kazarus avatar uedzen avatar hanbohamburger avatar  avatar levphon avatar HM avatar  avatar 阿喵 avatar  avatar Jay.M.Hu avatar Jiff Shen avatar cn1289 avatar wp3355168 avatar  avatar  avatar zj8487 avatar rain avatar xiaobai avatar RealForce1024 avatar  avatar 冯淼森 avatar Chuck Lu avatar hhhaiai avatar ieitZYB avatar  avatar  avatar  avatar bo li avatar  avatar  avatar hqx avatar leanne avatar neoddish avatar  avatar _ avatar  avatar Jesmin Ngo avatar  avatar  avatar  avatar

g6's Issues

关于 group 和 shape 的 api

在示例中看到如下的用法

nameGroup.addShape('text', {
  attrs:{
    x: x,
    y: y + 20 * i,
    text: field.name,
    fill: '#333',
    textBaseline: 'top'
  }
});

splitLine = group.addShape('line', {
  attrs: {
    stroke: '#fff'
  }
});

关于 group 和 shape 的用法,比如支持哪些 attrs,在官网文档没有找到,可以补充一下吗。

撤销功能最多可以撤销几步

撤销功能是不是最多可以撤销4步,是否支持撤销到初始化状态,是否可以支持设置撤销几步,有没有这个打算

自定义图形,nodes里面的x,y失效?

安装的版本是:

npm install @antv/g6

我自定义了几个图标,代码大致如下:

// 注册一个路由器的图标
G6.registNode('router', {
  draw: function(cfg, group) {
    group.addShape('path', {
      attrs: {
        path: 'M0 12.3 V28.9 A 24.9 11.0 0 1 0 49.8 28.9 V12.3 Z',
        fill: '#dbdde1'
      }
    });
    group.addShape('ellipse', {
      attrs: {
        x: 24.9,
        y: 12.3,
        rx: 24.9,
        ry: 12.3,
        fill: '#e2e4e9'
      }
    });
    group.addShape('ellipse', {
      attrs: {
        x: 24.9,
        y: 12.3,
        rx: 23.5,
        ry: 11.6,
        fill: '#eeeff2'
      }
    });
    group.addShape('path', {
      attrs: {
        path: 'M2.3,10.1 L4.6,7.9 L16.5,9.6 L17.7,8.6 L20.5,11.7 L12.4,13.5 L13.6,12.2Z M24.8,10.0 L28.3,6.9 L26.4,6.4 L34.6,4.3 L34.1,7.6 L31.7,7.4 L27.9,11.1Z M28.0,12.7 L35.7,11.4 L34.6,12.5 L46.0,14.8 L43.8,16.9 L31.7,14.1 L29.6,16.2Z M20.7,13.9 L24.3,14.5 L20.0,18.5 L22.6,19.3 L14.6,20.8 L14.3,17.2 L16.5,17.7Z',
        fill: '#e85464'
      }
    });
    return group.addShape('rect', {
      attrs: {
        x: 0,
        y: 0,
        width: 49.8,
        height: 40
      }
    });
  },
  afterDraw: function(cfg, group, router) {
    cfg.size = 10
    group.addShape('text', {
      attrs: {
        x: 20,
        y: 51.3,
        fontFamily: '宋体',
        text: cfg.label,
        stroke: '#000',
        textAlign: 'center'
      }
    });
  },
  getAnchorPoints: function(cfg, group) {
    return [
      [0.5, 1], // 上面边的中点
      [1, 0.5], // 右边边的中点
      [0.5, 0], // 下边边的中点
      [0, 0.5] // 左边边的中点
    ]
  }
});

然后我渲染的数据如下:

var nodes = [
  {
    "id": "595b5e7e1d41c86f00adc371",
    "name": "switch_center",
    "host_id": "switch_center",
    "node_ip": "10.10.2.1",
    "node_type": "05401202",
    "linked": "1",
    "weight": 40,
    "y": 358.36920299208396,
    "x": 636.8554312518343,
    "shape": "router"
  },
  .....
]

结果是,这一类图标渲染出来的位置在坐标原点。

如何重新布局?

你好,我参照官方示例进行布局,如下所示。但是我的需求会动态添加/删除一些 node 和 edge,请问一下如何触发重新布局呢?

var Layout = G6.Layout;
var margin = 60;
var height = 800 - 2 * margin;
var width = 500 - 2 * margin;
var nodes = data.nodes;
var edges = data.edges;
var layout = new Layout.Flow({
  nodes: nodes,
  edges: edges
});
nodes = layout.getNodes();
nodes.map(function(node) {
  var x = node.x * width + margin;
  var y = node.y * height + margin;
  node.x = y;
  node.y = x;
});

锚点连接问题

能不能处理以下两种情况
1,一个锚点连接过一次就不能进行第二次连接了
2,控制一个图形左侧的锚点不能和另外一个图形左侧的锚点进行连接

节点中可以存储节点

节点可以作为容器,可以为容器节点添加子节点,可以获取容器节点下的子节点数组,当容器节点移动时子节点一起移动,可以单独选择子节点。

动画

在更新 添加 删除 数据模型的时候 能不能 提供个动画 接口啊

例如 : graph.update(item, model,animate = true)

关于g6 net数据大的问题

在之前数据库表的基础上做了一个模拟数据,到1000张左右的时候 会比较卡,请问如何处理数据量大的问题呢?
`$(function () {

    var dataObj = {
        nodes: [],
        edges: [],
    };

    for (var i = 0; i < 1500; i++) {
        var nodesObj = {
            "shape": "table",
            "x": Math.floor(Math.random() * 9999),
            "y": Math.floor(Math.random() * 9999),
            "id": "d62q1519",
            "title": "Division",
            "type": "B",
            "fields": [
                {
                    "name": "Employee number",
                    "type": "Numberic(5)",
                    "key": "<pk>"
                },
                {
                    "name": "Emp_Employee number",
                    "type": "Numberic(5)",
                    "key": "<fk1>"
                },
                {
                    "name": "Division",
                    "type": "Numberic(5)",
                    "key": "<fk2>"
                },
                {
                    "name": "FirstName",
                    "type": "Chart(30)",
                    "key": ""
                }
            ]
        };
        var edgesObj = {
            "shape": "arrow",
            "source": "d62d1569",
            "id": "d6cb23c5",
            "target": "d62d1519",
            "controlPoints": [
                {
                    "x": Math.floor(Math.random() * 9999),
                    "y": Math.floor(Math.random() * 9999)
                },
                {
                    "x": Math.floor(Math.random() * 9999),
                    "y": Math.floor(Math.random() * 9999)
                },
                {
                    "x": Math.floor(Math.random() * 9999),
                    "y": Math.floor(Math.random() * 9999)
                }
            ],
            "relation": "service",
            "sourceAnchor": 2
        };
        edgesObj.source = edgesObj.target = nodesObj.id = Math.random().toString(36).substr(2);
        edgesObj.id = Math.random().toString(36).substr(2);

        dataObj.nodes.push(nodesObj);
        dataObj.edges.push(edgesObj);
    }

    var Util = G6.Util;
    G6.registNode('table', {
        draw: function (cfg, group) {
            var x = cfg.x;
            var y = cfg.y;
            var origin = cfg.origin;
            var fields = origin.fields;
            var backRect = group.addShape('rect', {
                attrs: {
                    stroke: 'blue',
                    fill: cfg.color
                }
            });
            var nameGroup = group.addGroup();
            var typeGroup = group.addGroup();
            var keyGroup = group.addGroup();
            var lineHeight = 20;
            var marginRight = 10;
            var padding = 6;
            var l = fields.length;
            var fontHeight;
            var anchorPoints = [];
            var title;
            var titleBox;
            var nameBox;
            var typeBox;
            var keyBox;
            var width;
            var height;
            var splitLine;
            title = group.addShape('text', {
                attrs: {
                    x: x,
                    y: y,
                    text: origin.title,
                    fill: '#333',
                    textBaseline: 'top',
                    textAlign: 'center'
                }
            });
            splitLine = group.addShape('line', {
                attrs: {
                    stroke: '#fff'
                }
            });
            Util.each(fields, function (field, i) {
                nameGroup.addShape('text', {
                    attrs: {
                        x: x,
                        y: y + 20 * i,
                        text: field.name,
                        fill: '#333',
                        textBaseline: 'top'
                    }
                });
                typeGroup.addShape('text', {
                    attrs: {
                        x: x,
                        y: y + 20 * i,
                        text: field.type,
                        fill: '#333',
                        textBaseline: 'top'
                    }
                });
                keyGroup.addShape('text', {
                    attrs: {
                        x: x,
                        y: y + 20 * i,
                        text: field.key,
                        fill: '#333',
                        textBaseline: 'top'
                    }
                });
            });
            titleBox = title.getBBox();
            nameBox = nameGroup.getBBox();
            typeBox = typeGroup.getBBox();
            keyBox = keyGroup.getBBox();
            width = nameBox.width + typeBox.width + keyBox.width + 3 * marginRight + 2 * padding;
            height = Math.max(nameBox.height, typeBox.height, keyBox.height) + 4 * padding + titleBox.height;
            fontHeight = nameGroup.get('children')[0].getBBox().height;
            title.translate(0, -height / 2 + padding);
            nameGroup.translate(-width / 2 + padding, -height / 2 + titleBox.height + 3 * padding);
            typeGroup.translate(-width / 2 + nameBox.width + marginRight + padding, -height / 2 + titleBox.height + 3 * padding);
            keyGroup.translate(-width / 2 + nameBox.width + typeBox.width + 2 * marginRight + padding, -height / 2 + titleBox.height + 3 * padding);
            splitLine.attr({
                x1: cfg.x - width / 2,
                y1: cfg.y - height / 2 + 2 * padding + titleBox.height,
                x2: cfg.x + width / 2,
                y2: cfg.y - height / 2 + 2 * padding + titleBox.height
            });
            backRect.attr({
                x: x - width / 2,
                y: y - height / 2,
                width: width,
                height: height,
                stroke: 'blue',
                fill: cfg.color
            });
            Util.each(fields, function (field, i) {
                var r = ( titleBox.height + i * (nameBox.height + lineHeight - fontHeight) / l + fontHeight / 2 + 3 * padding) / height;
                anchorPoints.push([0, r]);
                anchorPoints.push([1, r]);
            });
            group.set('anchorPoints', anchorPoints);
            return backRect;
        },
        getAnchorPoints: function (cfg, group) {
            var anchorPoints = group.get('anchorPoints');
            anchorPoints.unshift([0.5, 0]);   // 上中
            anchorPoints.push([0.5, 1]);      // 下中
            return anchorPoints;
        }
    });
    var net = new G6.Net({
        id: 'c1',            // 容器ID
        height: 900,         // 画布高
        fitView: 'autoZoom', // 自动缩放
        grid: {
            cell: 10           // 网格大小
        }
    });
    net.source(dataObj.nodes, dataObj.edges);
    net.node().color('type', function (val) {
        if (val === "B") {
            return G6.Global.colors[0];
        }
        if (val === "C") {
            return G6.Global.colors[1];
        }
    });
    net.edge().label('relation');
    net.render();
});`

关于插入图片

定义的节点image只支持http开头的吗,我写本地的不好用

`
addImage.on('click',function(ev){
net.beginAdd('node',{
shape:'china.png'//这个位置如果换成加http的是好使得
}) })

`

关于removeBehaviour方法失效

hi
我的流程是这样的:
进入页面后,默认是complicated模式,点击“编辑”按钮后,切换到“edit”模式,我初始化net的时候,没有设置默认的“modes”字段。
现在的问题是:切换到“edit”模式后,双击画布报错,错误原因是“shortcut”这个行为。
我现在这样做:

function openEdit() {
  console.log('进入编辑模式');

  net.changeMode('edit');
  net.removeBehaviour('shortcut', 'edit');
  net.removeBehaviour('clickActive', 'edit');
}

但是双击画布以后还是会报错。
或者麻烦告诉我你们默认设置的“edit”模式都包括什么行为?我自定义一下“modes”字段。

在自定义节点里添加一个菱形会报错

G6.registNode("compositeNode", {
  draw: function(cfg, group) {
    var shape = group.addShape("rect", {
      attrs: {
        x: cfg.x - 60,
        y: cfg.y - 30,
        width: 120,
        height: 60,
        fill: "#fff",
        stroke: "lightblue"
      }
    });
    group.addShape("rhombus");
    group.addShape("text", {
      attrs: {
        x: cfg.x,
        y: cfg.y,
        fill: "black",
        text: "自定义图形",
        textAlign: "center"
      }
    });
    return shape;
  },
  getAnchorPoints: function() {
    return [[0.5, 0], [1, 0.5], [0.5, 1], [0, 0.5]];
  }
});

我想组合一个自定义节点里面有矩形和菱形。但是这样会报错

Uncaught TypeError: u[r] is not a constructor

把 group.addShape("rhombus"); 去掉就好了

codepen demo

updateAnchor怎么用

updateAnchor怎么用,在api里面没有看到相关讲解,我想控制指定某个锚点可连线和不可连线

如何动态修改一个节点样式?

我希望点击一个节点改变这个节点的一些样式 onClick事件里应该怎样写呢?是改变节点属性然后graph.refresh/update吗?
最开始我的想法是graph.edge().style('id', id => id === activeId ? 'custom-style': '')
但是发现我在onClick里面写什么都不会重新设置一遍style
现在有点蒙 不知道应该是具体用什么思路搞这件事

如何添加节点内局部自定义事件

非常喜欢 G6 ,给项目组点赞。

我想要捕获节点的局部点击事件,请问一下如何实现呢?我们要实现一个自定义节点,捕获类似 tree 节点右侧的 "+" 号的点击事件。目前从文档和示例来看,只能获取到 node 和 edge 这个级别的事件。

smoothArrow连接固定不变

image
针对自定义的图形,是不是在使用smoothArrow连接两个图形的锚点时,图形的位置发生改变,但是线的连接点连接的还是当初的锚点,不会跟着一起改变

G6 0.X -> G6 1.0 升级指南

概述

该文档是 G6 0.X -> G6 1.0 的升级指南文档,如果有你觉得描述的不够清晰的地方,升级有困难的话,敬请联系我们

原来的 Graph 既是现在的 Net

Graph 在 G6 1.0 中已经沉为抽象类,用户不应该直接实例化 Graph 使用。1.0 中 Net 基本含 0.X Graph 所有属性、方法。从 0.X 迁 1.X 的用户应将所有的 Graph 改为 Net。

新的锚点描述

锚点在关系图中无非是一个至关重要的概念,如果 0.X 中你使用了自定义锚点,应参看下文。

过去的锚点,我们定义了上(0)右(1)下(2)左(3),四个边,然后在通过第二个参数确定锚点的位置,如左图所示。这样不仅理解起来复杂,而且还有一个硬伤 —— 锚点无法定义到图形上!在新的锚点机制里,我们以左上角为(0,0)点,将锚点的范围拓展至了整个图形的包围盒平面内,如右图所示:

这样我们不仅能把锚点定义到图形包围盒边上,还能定义到包围盒内图,以做到锚点跟图形精确关联,如下图所示:

再见无穷尽的xxxable

诸如:selectabledragablezoomable,在 1.0 后,应用行为模式的交互插拔机制实现,比如:

0.X 中

var graph = new Graph({
  zoomable: false
});

等于 1.X 中

var net = new Net();
net.removeBehaviour(['wheelZoom']);

行为、模式的插拔组装,参见Demo;

调整初始化视口应该用fitView

0.x 中有时我们会render结束后,调用autoZoom方法,让图适应画布。1.X 中这种方法被废弃,需要在初始化图时配置fitView,以决定初始化时画布的视口。Graph API,fitView 属性。

统一输入输出 save && read

在使用关系图开发的过程中,我们常常需要导出导入数据,以满足关系图的存储、分享、编辑的功能。0.X 中 graph.savegraph.srouce 并没有严格对照。 G6 1.0 后,我们对这部分的需求做了总结。在 Graph 定义了一对相互对照的接口,read <==> save,后面用户应该严格通过这两个该接口导入导出数据。

读入数据 -- read

/**
 * 导入数据
 * @param  {Object}  data   通过save导出的数据
 */
graph.read(data);

保存数据 -- save

/**
 * 导出数据
 * @return  {Object}  data  导出的数据
 */
graph.save();

获得数据对象是不是应该更方便一点

graph.edge().color(dim, fun) 边颜色映射
graph.edge().size(dim, fun) 边大小映射
graph.edge().shape(dim, fun) 边形状映射
graph.edge().label(dim, fun) 边文本映射
graph.edge().style(dim, fun) 样式映射
graph.edge().tooltip(dim, fun) 提示信息映射

这一系列方法 参数是否应该直接是(edge) => {} ?node()同理,为什么不直接把对象暴露出来呢?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.