# G6

G6 是一个图可视化引擎。

<script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.4.7/dist/g6.min.js"></script>
<script>
console.log(G6.Global.version);//查看版本
</script>

# G6基本创建

  • 创建容器

在 HTML 中创建一个用于容纳 G6 绘制的图的容器。G6 在绘制时会在该容器下追加 canvas 标签,然后将图绘制在其中。

<div id="mountNode"></div>
  • 数据

引入 G6 的数据源为 JSON 格式的对象。该对象中需要有节点(nodes)和边(edges)字段

<script>
  const initData = {
    // 点集
    nodes: [
      {
        id: 'node1', // 节点的唯一标识
        x: 100, // 节点横坐标
        y: 200, // 节点纵坐标
        label: '起始点', // 节点文本
      },
      {
        id: 'node2',
        x: 300,
        y: 200,
        label: '目标点',
      },
    ],
    // 边集
    edges: [
      // 表示一条从 node1 节点连接到 node2 节点的边
      {
        source: 'node1', // 起始点 id
        target: 'node2', // 目标点 id
        label: '我是连线', // 边的文本
      },
    ],
  };
</script>

注意

  • nodes 数组中包含节点对象,唯一的 id 是每个节点对象中必要的属性,x、 y 用于定位;
  • edges 数组中包含边对象,source 和 target 是每条边的必要属性,分别代表了该边的起始点 id 与 目标点 id。
  • 图实例化

图实例化时,至少需要为图设置容器、宽、高

 const graph = new G6.Graph({
    container: 'mountNode', // 指定挂载容器
    width: 800, // 图的宽度
    height: 500, // 图的高度
  });

还可以设置其他配置: fitView:Boolean ,适配画布,默认false;fitViewPadding画布周围留白,默认无,Number/Array(20/[20,40,10,30])

  • 图的渲染
graph.data(initData); // 加载数据
graph.render(); // 渲染

# G6元素及其配置

图的元素特指图上的节点 Node 和边 Edge 。

不论是节点还是边,它们的属性分为两种:

  • 样式属性 style:对应 Canvas 中的各种样式,在元素状态 State 发生变化时,可以被改变;
  • 其他属性:例如图形类型( type)、id(id )一类在元素状态 State 发生变化时不能被改变的属性。

例如,G6 设定 hover 或 click 节点,造成节点状态的改变,只能自动改变节点的样式属性(如 fill、stroke 等),其他属性(如 type 等)不能被改变。如果需要改变其他属性,要通过 graph.updateItem 手动配置。样式属性是一个名为 style 的对象, style 字段与其他属性并行。

//以节点元素为例 ,
//边元素的属性数据结构与节点元素相似,只是其他属性中多了 source 和 target 字段,代表起始和终止节点的 id。
{
  id: 'node0',          // 元素的 id
  shape: 'circle',      // 元素的图形
  size: 40,             // 元素的大小
  label: 'node0'        // 标签文字
  labelCfg: {           // 标签配置属性
    positions: 'center',// 标签的属性,标签在元素中的位置
    style: {            // 包裹标签样式属性的字段 style 与标签其他属性在数据结构上并行
      fontSize: 12,     // 标签的样式属性,文字字体大小
      // ...            // 标签的其他样式属性
    }
  }
  // ...,               // 其他属性
  style: {              // 包裹样式属性的字段 style 与其他属性在数据结构上并行
    fill: '#000',       // 样式属性,元素的填充色
    stroke: '#888',     // 样式属性,元素的描边色
    // ...              // 其他样式属性
  }
}

如果所有节点统一的属性配置,所有边统一的属性配置,可以使用defaultNode和defaultEdge来配置(不包括某些个性化设置)

  • defaultNode:节点在默认状态下的样式属性(style)和其他属性;
  • defaultEdge:边在默认状态下的样式属性(style)和其他属性。
const graph = new G6.Graph({
  // ...                   // 图的其他配置
  // 节点在默认状态下的样式配置(style)和其他配置
  defaultNode: {
    size: 30, // 节点大小
    // ...                 // 节点的其他配置
    // 节点样式配置
    style: {
      fill: 'steelblue', // 节点填充色
      stroke: '#666', // 节点描边色
      lineWidth: 1, // 节点描边粗细
    },
    // 节点上的标签文本配置
    labelCfg: {
      // 节点上的标签文本样式配置
      style: {
        fill: '#fff', // 节点标签文字颜色
      },
    },
  },
  // 边在默认状态下的样式配置(style)和其他配置
  defaultEdge: {
    // ...                 // 边的其他配置
    // 边样式配置
    style: {
      opacity: 0.6, // 边透明度
      stroke: 'grey', // 边描边颜色
    },
    // 边上的标签文本配置
    labelCfg: {
      autoRotate: true, // 边上的标签文本根据边的方向旋转
    },
  },
});

可以通过设置获取个性化设置

const nodes = remoteData.nodes;
nodes.forEach(node => {
  if (!node.style) {
    node.style = {};
  }
  switch (
    node.class // 根据节点数据中的 class 属性配置图形
  ) {
    case 'c0': {
      node.shape = 'circle'; // class = 'c0' 时节点图形为 circle
      break;
    }
    case 'c1': {
      node.shape = 'rect'; // class = 'c1' 时节点图形为 rect
      node.size = [35, 20]; // class = 'c1' 时节点大小
      break;
    }
    case 'c2': {
      node.shape = 'ellipse'; // class = 'c2' 时节点图形为 ellipse
      node.size = [35, 20]; // class = 'c2' 时节点大小
      break;
    }
  }
});

// 遍历边数据
const edges = remoteData.edges;
edges.forEach(edge => {
  if (!edge.style) {
    edge.style = {};
  }
  edge.style.lineWidth = edge.weight; // 边的粗细映射边数据中的 weight 属性数值
});

graph.data(remoteData);

{
  "nodes": [
    {"id": "0", "label": "n0", "class": "c0","x": 1000, "y": -100 },
    {"id": "1", "label": "n1", "class": "c0","x": 300, "y": -10 }

  ],
  "edges": [
    {"source": "0", "target": "1", "label": "e0-1", "weight": 1 },
    {"source": "0", "target": "2", "label": "e0-2", "weight": 2 } 
  ]
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Tutorial Demo</title>
  </head>
  <body>
    <div id="mountNode"></div>
    <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.1.0/build/g6.js"></script>
    <script>
      const graph = new G6.Graph({
        container: 'mountNode',
        width: 800,
        height: 600,
        fitView: true,
        fitViewPadding: [20, 40, 50, 20],
        defaultNode: {
          size: 30,
          labelCfg: {
            style: {
              fill: '#fff',
            },
          },
        },
        defaultEdge: {
          labelCfg: {
            autoRotate: true,
          },
        },
      });
      const main = async () => {
        const response = await fetch(
          'https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json',
        );
        const remoteData = await response.json();
        const nodes = remoteData.nodes;
        const edges = remoteData.edges;
        nodes.forEach(node => {
          if (!node.style) {
            node.style = {};
          }
          node.style.lineWidth = 1;
          node.style.stroke = '#666';
          node.style.fill = 'steelblue';
          switch (node.class) {
            case 'c1': {
              node.shape = 'rect';
              node.size = [35, 20];
              break;
            }
            case 'c2': {
              node.shape = 'ellipse';
              node.size = [35, 20];
              break;
            }
          }
        });
        edges.forEach(edge => {
          if (!edge.style) {
            edge.style = {};
          }
          edge.style.lineWidth = edge.weight;
          edge.style.opacity = 0.6;
          edge.style.stroke = 'grey';
        });

        graph.data(remoteData);
        graph.render();
      };
      main();
    </script>
  </body>
</html>

# G6布局layout

G6 提供了 9 种一般图的布局和 4 种树图的布局:

  • 一般图:

    • Random Layout:随机布局;
    • Force Layout:经典力导向布局:
  • Circular Layout:环形布局;

  • Radial Layout:辐射状布局;

  • MDS Layout:高维数据降维算法布局;

  • Fruchterman Layout:Fruchterman 布局,一种力导布局;

  • Dagre Layout:层次布局。

  • 树图布局:

    • Dendrogram Layout:树状布局(叶子节点布局对齐到同一层);
    • CompactBox Layout:紧凑树布局;
    • Mindmap Layout:脑图布局;
    • Intended Layout:缩进布局.

复杂的布局系统会打破适配规则,最好关闭fitView

const graph = new G6.Graph({
  // ...                      // 其他配置项
  layout: {                // Object,可选,布局的方法及其配置项,默认为 random 布局。
    type: 'force',         // 指定为力导向布局
    preventOverlap: true,  // 防止节点重叠
    // nodeSize: 30        // 节点大小,用于算法中防止节点重叠时的碰撞检测。由于已经在上一节的元素配置中设置了每个节点的 size 属性,则不需要在此设置 nodeSize。
  }
});

# G6交互行为

# 拖拽、缩放——内置的交互行为

const graph = new G6.Graph({
  // ...                                          // 其他配置项
  modes: {
    default: ['drag-canvas', 'zoom-canvas', 'drag-node'], // 允许拖拽画布、放缩画布、拖拽节点
  },
});

modes 定义了 G6 的模式,default 是默认的模式,还可以允许有其他的模式,比如:编辑模式 edit 等。不同的模式,用户能进行的行为可以不同,比如默认模式能拖拽画布,编辑模式不允许拖拽画布

在实例化图时,通过 nodeStateStyles 和 edgeStateStyles 两个配置项可以配置元素在不同状态下的样式。

const graph = new G6.Graph({
  // ...                           // 其他配置项
  // 节点不同状态下的样式集合
  nodeStateStyles: {
    // 鼠标 hover 上节点,即 hover 状态为 true 时的样式
    hover: {
      fill: 'lightsteelblue',
    },
    // 鼠标点击节点,即 click 状态为 true 时的样式
    click: {
      stroke: '#000',
      lineWidth: 3,
    },
  },
  // 边不同状态下的样式集合
  edgeStateStyles: {
    // 鼠标点击边,即 click 状态为 true 时的样式
    click: {
      stroke: 'steelblue',
    },
  },
});

# 监听事件并切换元素状态

G6 中所有元素监听都挂载在图实例上,如下代码中的 graph 对象是 G6.Graph 的实例,graph.on() 函数监听了某元素类型(node / edge)的某种事件(click / mouseenter / mouseleave / ... )。

// 在图实例 graph 上监听
graph.on('元素类型:事件名', e => {
  // do something
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Tutorial Demo</title>
	<style type="text/css">
		#mountNode{
			border: 1px solid red;
		}
	</style>
  </head>
  <body>
    <div id="mountNode"></div>
    <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.1.0/build/g6.js"></script>
    <script>
      const graph = new G6.Graph({
        container: 'mountNode',
        width: 800,
        height: 600,
        // 节点默认配置
        defaultNode: {
          labelCfg: {
            style: {
              fill: '#fff',
            },
          },
        },
        // 边默认配置
        defaultEdge: {
          labelCfg: {
            autoRotate: true,
          },
        },
        // 节点在各状态下的样式
        nodeStateStyles: {
          // hover 状态为 true 时的样式
          hover: {
            fill: 'lightsteelblue',
          },
          // click 状态为 true 时的样式
          click: {
            stroke: '#000',
            lineWidth: 3,
          },
        },
        // 边在各状态下的样式
        edgeStateStyles: {
          // click 状态为 true 时的样式
          click: {
            stroke: 'steelblue',
          },
        },
        // 布局
        layout: {
          type: 'force',
          linkDistance: 100,
          preventOverlap: true,
          nodeStrength: -30,
          edgeStrength: 0.1,
        },
        // 内置交互
        modes: {
          default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
        },
      });

      const main = async () => {
        const response = await fetch(
          'https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json',
        );
        const remoteData = await response.json();

        const nodes = remoteData.nodes;
        const edges = remoteData.edges;
        nodes.forEach(node => {
          if (!node.style) {
            node.style = {};
          }
          node.style.lineWidth = 1;
          node.style.stroke = '#666';
          node.style.fill = 'steelblue';
          switch (node.class) {
            case 'c0': {
              node.shape = 'circle';
              node.size = 30;
              break;
            }
            case 'c1': {
              node.shape = 'rect';
              node.size = [35, 20];
              break;
            }
            case 'c2': {
              node.shape = 'ellipse';
              node.size = [35, 20];
              break;
            }
          }
        });
        edges.forEach(edge => {
          if (!edge.style) {
            edge.style = {};
          }
          edge.style.lineWidth = edge.weight;
          edge.style.opacity = 0.6;
          edge.style.stroke = 'grey';
        });

        graph.data(remoteData);
        graph.render();

        // 监听鼠标进入节点
        graph.on('node:mouseenter', e => {
          const nodeItem = e.item;
          // 设置目标节点的 hover 状态 为 true
          graph.setItemState(nodeItem, 'hover', true);
        });
        // 监听鼠标离开节点
        graph.on('node:mouseleave', e => {
          const nodeItem = e.item;
          // 设置目标节点的 hover 状态 false
          graph.setItemState(nodeItem, 'hover', false);
        });
        // 监听鼠标点击节点
        graph.on('node:click', e => {
          // 先将所有当前有 click 状态的节点的 click 状态置为 false
          const clickNodes = graph.findAllByState('node', 'click');
          clickNodes.forEach(cn => {
            graph.setItemState(cn, 'click', false);
          });
          const nodeItem = e.item;
          // 设置目标节点的 click 状态 为 true
          graph.setItemState(nodeItem, 'click', true);
        });
        // 监听鼠标点击节点
        graph.on('edge:click', e => {
          // 先将所有当前有 click 状态的边的 click 状态置为 false
          const clickEdges = graph.findAllByState('edge', 'click');
          clickEdges.forEach(ce => {
            graph.setItemState(ce, 'click', false);
          });
          const edgeItem = e.item;
          // 设置目标边的 click 状态 为 true
          graph.setItemState(edgeItem, 'click', true);
        });
      };
      main();
    </script>
  </body>
</html>

# G6插件和交互工具

# 插件

  • Step 1: 引入插件;
  • Step 2: 实例化插件;
  • Step 3: 在实例化图时将插件的实例配置到图上。
# 缩略图 (Minimap) 栅格grid
// 实例化插件
const minimap = new G6.Minimap({
  size: [100, 100],
  className: 'minimap',
  type: 'delegate',
});
const grid = new G6.Grid();
// 实例化图
const graph = new G6.Graph({
  // ...                           // 其他配置项
  plugins: [minimap, grid], // 将实例配置到图上
});

# 交互工具

  • Step 1: 在实例化图时配置 modes;
  • Step 2: 为交互工具定义样式。
# tooltip 节点提示框
const graph = new G6.Graph({
  modes: {
    default: [
      // ...
      {
        type: 'tooltip', // 提示框
        formatText(model) {
          // 提示框文本内容
          const text = 'label: ' + model.label + '<br/> class: ' + model.class;
          return text;
        },
      },
    ],
  },
});

tooltip 实际上是一个悬浮的 <div> 标签,因此可在 HTML 的 <style> 标签或 CSS 中设置样式。下面展示在 HTML 中设置样式:

.g6-tooltip {
      border: 1px solid #e2e2e2;
      border-radius: 4px;
      font-size: 12px;
      color: #545454;
      background-color: rgba(255, 255, 255, 0.9);
      padding: 10px 8px;
      box-shadow: rgb(174, 174, 174) 0px 0px 10px;
    }
# edge-tooltip 边提示框
const graph = new G6.Graph({
  modes: {
    default: [
      // ...
      {
        type: 'tooltip', // 节点提示框
        // ...
      },
      {
        type: 'edge-tooltip', // 边提示框
        formatText(model) {
          // 边提示框文本内容
          const text =
            'source: ' +
            model.source +
            '<br/> target: ' +
            model.target +
            '<br/> weight: ' +
            model.weight;
          return text;
        },
      },
    ],
  },
});
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tutorial Demo</title>
  <style type="text/css">
  	
	.g6-tooltip {
	  border: 1px solid #e2e2e2;
	  border-radius: 4px;
	  font-size: 12px;
	  color: #545454;
	  background-color: rgba(255, 255, 255, 0.9);
	  padding: 10px 8px;
	  box-shadow: rgb(174, 174, 174) 0px 0px 10px;
	}

  </style>
</head>
<body>
  <div id="mountNode"></div>
  <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.4.7/dist/g6.min.js"></script>
  <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
  <script type="text/javascript">
  	// 实例化 Minimap 插件
const minimap = new G6.Minimap({
  size: [ 100, 100 ],
  className: "minimap",
  type: 'delegate'
});

// 实例化 Grid 插件
const grid = new G6.Grid();

const graph = new G6.Graph({
  container: 'mountNode',
  width: 800,
  height: 600,
  defaultNode: {
    labelCfg: {
      style: {
        fill: '#fff'
      }
    }
  },
  defaultEdge: {
    labelCfg: {
      autoRotate: true
    }
  },
  nodeStateStyles: {
    hover: {
      fill: 'lightsteelblue'
    },
    click: {
      stroke: '#000',
      lineWidth: 3
    }
  },
  edgeStateStyles: {
    click: {
      stroke: 'steelblue'
    }
  },
  layout: {
    type: 'force',
    linkDistance: 100,
    preventOverlap: true,
    nodeStrength: -30,
    edgeStrength: 0.1
  },
  modes: {
    default: [ 'drag-node', 'drag-canvas', 'zoom-canvas',
              // 点提示框交互工具的配置
              {
                type: 'tooltip',
                formatText(model) {
                  const text = 'label: ' + model.label
                  + '<br/> class: ' + model.class;
                  return text;
                },
                shouldUpdate: e => {
                  return true;
                }
              },
              // 边提示框交互工具的配置
              {
                type: 'edge-tooltip',
                formatText(model) {
                  const text = 'source: ' + model.source
                  + '<br/> target: ' + model.target
                  + '<br/> weight: ' + model.weight;
                  return text;
                },
                shouldUpdate: e => {
                  return true;
                }
              }
             ]
  },
  plugins: [ minimap, grid ]    // 将 Minimap 和 Grid 插件的实例配置到图上
});
//$.getJSON('https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json', data => {
const main = async () => {
  const response = await fetch('https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json');
  const data = await response.json();
  console.log(data);
  const nodes = data.nodes;
  const edges = data.edges;
  nodes.forEach(node => {
    if (!node.style) {
      node.style = {};
    }
    node.style.lineWidth = 1;
    node.style.stroke = '#666';
    node.style.fill = 'steelblue';
    switch (node.class) {
      case 'c0': {
        node.shape = 'circle';
        node.size = 30;
        break;
      }
      case 'c1': {
        node.shape = 'rect';
        node.size = [ 35, 20 ];
        break;
      }
      case 'c2': {
        node.shape = 'ellipse';
        node.size = [ 35, 20 ];
        break;
      }
    }
  });
  edges.forEach(edge => {
    if (!edge.style) {
      edge.style = {};
    }
    edge.style.lineWidth = edge.weight;
    edge.style.opacity = 0.6;
    edge.style.stroke = 'grey';
  });
  
  
  graph.data(data);
  graph.render();
  
  graph.on('node:mouseenter', e => {
    const nodeItem = e.item;
    graph.setItemState(nodeItem, 'hover', true);
  });
  graph.on('node:mouseleave', e => {
    const nodeItem = e.item;
    graph.setItemState(nodeItem, 'hover', false);
  });
  graph.on('node:click', e => {
    const clickNodes = graph.findAllByState('node', 'click');
    clickNodes.forEach(cn => {
      graph.setItemState(cn, 'click', false);
    });
    const nodeItem = e.item;
    graph.setItemState(nodeItem, 'click', true);
  });
  graph.on('edge:click', e => {
    const clickEdges = graph.findAllByState('edge', 'click');
    clickEdges.forEach(ce => {
      graph.setItemState(ce, 'click', false);
    });
    const edgeItem = e.item;
    graph.setItemState(edgeItem, 'click', true);
  });
};
main();
  </script>
</body>
</html>

antv G6 关于元素类型,shape 字段即将被废弃,请使用 type 代替

# G6扩展

G6 的内置节点包括 circle,rect,ellipse,diamond,triangle,star,image,modelRect。

circle的size是直径,rect的size是数组[100,50]等等

内置的节点支持的通用属性

名称 是否必须 类型 备注
id true String 节点编号
x false Number x 坐标
y false Number y 坐标
type(shape会被废弃) false String 节点图形,默认为 'circle'
size false Number / Array 节点的大小
anchorPoints false Array 指定边连入节点的连接点的位置(相对于该节点而言),可以为空。例如: [0, 0],代表节点左上角的锚点,[1, 1],代表节点右下角的锚点
style false Object 节点的样式属性。
label false String 文本文字
labelCfg false Object 文本配置项

样式属性 style Object 类型。通过 style 配置来修改节点的填充色、边框颜色、阴影等属性。

名称 类型 备注
fill String 节点填充色
stroke String 节点的描边颜色
lineWidth Number 描边宽度
lineDash Number[] 描边虚线,数组代表实、虚长度
shadowColor String 阴影颜色
shadowBlur Number 阴影范围
shadowOffsetX Number 阴影 x 方向偏移量
shadowOffsetY Number 阴影 y 方向偏移量
opacity Number 设置绘图的当前 alpha 或透明值
fillOpacity Number 设置填充的 alpha 或透明值
cursor String 鼠标在该节点上时的鼠标样式,CSS 的 cursor 选项都支持

labelCfg Object 类型。配置标签文本

名称 类型 备注
position String 文本相对于节点的位置,目前支持的位置有: 'center','top','left','right','bottom'。默认为 'center'
offset Number 文本的偏移,position 为 'bottom' 时,文本的上方偏移量;position 为 'left' 时,文本的右方偏移量;以此类推在其他 position 时的情况。
style Object 标签的样式属性。

# 节点的配置方法

实例化图时全局配置,在数据中动态配置,使用 graph.node(nodeFn) 函数配置 使用 graph.node(nodeFn) 配置 > 数据中动态配置 > 实例化图时全局配置

# graph.node()

该方法可以为不同节点进行不同的配置。

  • 该方法必须在 render 之前调用,否则不起作用;
  • 由于该方法优先级最高,将覆盖其他地方对节点的配置,这可能将造成一些其他配置不生效的疑惑;
  • 该方法在增加元素、更新元素时会被调用,如果数据量大、每个节点上需要更新的内容多时,可能会有性能问题。
// const data = ...
// const graph = ...
graph.node(node => {
  return {
    id: node.id,
    shape: 'rect',
    style: {
      fill: 'blue',
    },
  };
});

graph.data(data);
graph.render();

# circle

linkPoints Object 类型。可以指定节点周围「上、下、左、右」四个方向上的四个小圆点

区分于 anchorPoints: anchorPoints 是真正用于指定该节点相关边的连入位置的「数组」,见 anchorPoints;而 linkPoints 仅是指定是否「绘制」出四个圆点,不起实际的连接相关边的作用。二者常常配合使用。

const data = {
  // ... data 内容
};
const graph = new G6.Graph({
  // ... 图的其他属性
  defaultNode: {
    // ... 其他属性
    linkPoints: {
      top: true,
      bottom: true,
      left: true,
      right: true,
      fill: '#fff',
      size: 5,
    },
  },
});

还可以设置图标icon

名称 含义 类型 备注
show 是否显示 icon Boolean 默认为 false,不显示
width icon 的宽度 Number 默认为 16
height icon 的高度 Number 默认为 16
img icon 的地址 String -
const data = {
  // ... data 内容
};
const graph = new G6.Graph({
  // ... 图的其他属性
  defaultNode: {
    // ... 其他属性
    icon: {
      show: true,
      //img: '...', 可更换为其他图片地址
      width: 25,
      height: 25,
    },
  },
});
// ...

# ellipse

size 为 Number 时,效果为一个圆形。为 Array 时,size[0] 为椭圆长轴长度,size[1] 为椭圆短轴长度

# Triangle

  • size 三角形的边长 Number Array
  • direction 三角形的方向 String 可取值:'up','down','left','right'。默认为 'up'

# image

可根据需要裁剪

# ModelRect

名称 含义 类型 备注
preRect 左侧的小矩形 Object modelRect 节点特有
logoIcon 左侧的 logo 图标 Object modelRect 节点特有
stateIcon 右侧的状态图标 Object modelRect 节点特有
description 节点主要文本下方的描述文本 String modelRect 节点特有
// 节点中 icon 配置
logoIcon: {
  // 是否显示 icon,值为 false 则不渲染 icon
  show: true,
  x: 0,
  y: 0,
  // icon 的地址,字符串类型
  img: 'https://gw.alipayobjects.com/zos/basement_prod/4f81893c-1806-4de4-aff3-9a6b266bc8a2.svg',
  width: 16,
  height: 16,
  // 用于调整图标的左右位置
  offset: 0
},
// 节点中表示状态的 icon 配置
stateIcon: {
  // 是否显示 icon,值为 false 则不渲染 icon
  show: true,
  x: 0,
  y: 0,
  // icon 的地址,字符串类型
  img: 'https://gw.alipayobjects.com/zos/basement_prod/300a2523-67e0-4cbf-9d4a-67c077b40395.svg',
  width: 16,
  height: 16,
  // 用于调整图标的左右位置
  offset: -5
}

# G6边

  • line:直线,不支持控制点;
  • polyline:折线,支持多个控制点;
  • arc:圆弧线;
  • quadratic:二阶贝塞尔曲线;
  • cubic:三阶贝塞尔曲线;
  • cubic-vertical:垂直方向的三阶贝塞尔曲线,不考虑用户从外部传入的控制点;
  • cubic-horizontal:水平方向的三阶贝塞尔曲线,不考虑用户从外部传入的控制点;
  • loop:自环。
	const data = {
  nodes: [
    { id: '1', x: 50, y: 50, size: 20 },
    { id: '2', x: 150, y: 50, size: 20 },
  
  ],
  edges: [
    { source: '1', target: '2', shape: 'line', label: 'line' },
    { source: '3', target: '4', shape: 'polyline', label: 'polyline',style:{
		stroke:"green",
		cursor:`pointer`,
		lineAppendWidth:10//不好点击边进行操作的时候可适当增大点击范围
	} },
  ],
};

const graph = new G6.Graph({
  container: 'mountNode',
  width: 1500,
  height: 300,
  linkCenter: true, // 使边连入节点的中心
});
graph.data(data);
graph.render();

# line

const graph = new G6.Graph({
  container: 'mountNode',
  width: 800,
  height: 600,
  defaultEdge: {
    type: 'line',
    // 其他配置
  },
});

还可以单独配置line的color,不放在style里(style里用stroke,优先color配色)

# polyline

color: '#87e8de',
style: {
  offset: 20,  // 拐弯处距离节点最小距离
  radius: 10,  // 拐弯处的圆角弧度,若不设置则为直角
  lineWidth: 2,
  stroke: '#87e8de'
},
label: '边的标签文字',
labelCfg: {
  refX: 10,  // 文本在 x 方向偏移量
  refY: 10,  // 文本在 y 方向偏移量
  style: {
    fill: '#595959'
  }
}

# quadratic

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tutorial Demo</title>
  <style type="text/css">
  	
	.g6-tooltip {
	  border: 1px solid #e2e2e2;
	  border-radius: 4px;
	  font-size: 12px;
	  color: #545454;
	  background-color: rgba(255, 255, 255, 0.9);
	  padding: 10px 8px;
	  box-shadow: rgb(174, 174, 174) 0px 0px 10px;
	}

  </style>
</head>
<body>
  <div id="mountNode"></div>
  <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.4.7/dist/g6.min.js"></script>
  <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
  <script type="text/javascript">
	const data = {
  nodes: [
    {
      id: 'node0',
      x: 100,
      y: 100,
      size: 20,
    },
    {
      id: 'node1',
      x: 200,
      y: 100,
      size: 20,
    },
  ],
  edges: [
    {
      source: 'node0',
      target: 'node1',
      type: 'quadratic',
      label: 'quadratic',
    },
  ],
};
const graph = new G6.Graph({
  container: 'mountNode',
  width: 800,
  height: 600,
  defaultEdge: {
    // type: 'quadratic',  // 在数据中已经指定 type,这里无需再次指定
    style: {
      stroke: '#088',
      endArrow: true,
      lineWidth: 3,
    },
  },
});
graph.data(data);
graph.render();
  </script>
</body>
</html>

# 节点与边的层级

groupByTypes 是图的一个配置项,当其为默认值 true 时,所有节点在一个名为 nodeGroup 的分组,所有边在另一个名为 edgeGroup 的分组,且 nodeGroup 在 edgeGroup 上层。将其设置为 false 后,将不存在 nodeGroup 和 edgeGroup,所有节点和边在同一个分组,它们的层级根据生成的顺序决定。

const graph = new G6.Graph({
  // ...  // 其他配置
  groupByTypes: false,
});
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tutorial Demo</title>
  <style type="text/css">
  	
	.g6-tooltip {
	  border: 1px solid #e2e2e2;
	  border-radius: 4px;
	  font-size: 12px;
	  color: #545454;
	  background-color: rgba(255, 255, 255, 0.9);
	  padding: 10px 8px;
	  box-shadow: rgb(174, 174, 174) 0px 0px 10px;
	}

  </style>
</head>
<body>
  <div id="mountNode"></div>
  <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.4.7/dist/g6.min.js"></script>
  <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
  <script type="text/javascript">
// 数据源
const data = {
  nodes: [
    {
      id: 'node0',
      x: 100,
      y: 100,
      size: 20,
    },
    {
      id: 'node1',
      x: 200,
      y: 200,
      size: 20,
    },
    {
      id: 'node2',
      x: 150,
      y: 150,
      size: 20,
    },
    {
      id: 'node3',
      x: 150,
      y: 250,
      size: 20,
    },
    {
      id: 'node4',
      x: 150,
      y: 200,
      size: 20,
    },
  ],
  edges: [
    {
      id: 'edge0',
      source: 'node0',
      target: 'node1',
    },
    {
      id: 'edge1',
      source: 'node2',
      target: 'node3',
    },
  ],
};

// 实例化图
const graph = new G6.Graph({
  container: 'mountNode',
  groupByTypes: false,
  width: 800,
  height: 600,
  // 为方便演示,加粗边
  defaultEdge: {
    style: {
      lineWidth: 2,
    },
  },
});



// 读取数据
graph.data(data);
// 渲染图
graph.render();
// const nodes = graph.getNodes();
// // 遍历节点实例,将所有节点提前。
// nodes.forEach(node => {
//   node.toFront();
// });
// // 更改层级后需要重新绘制图
// graph.paint();


// 鼠标进入节点事件
graph.on('edge:mouseenter', ev => {
  // 获得鼠标当前目标边
  const edge = ev.item;
  // 该边的起始点
  const source = edge.getSource();
  // 该边的结束点
  const target = edge.getTarget();
  // 先将边提前,再将端点提前。这样该边两个端点还是在该边上层,较符合常规。
  edge.toFront();
  source.toFront();
  target.toFront();
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});

graph.on('edge:mouseleave', ev => {
  // 获得图上所有边实例
  const edges = graph.getEdges();
  // 遍历边,将所有边的层级放置在后方,以恢复原样
  edges.forEach(edge => {
    edge.toBack();
  });
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});

graph.on('node:mouseenter', ev => {
  // 获得鼠标当前目标节点
  const node = ev.item;
  // 获取该节点的所有相关边
  const edges = node.getEdges();
  // 遍历相关边,将所有相关边提前,再将相关边的两个端点提前,以保证相关边的端点在边的上方常规效果
  edges.forEach(edge => {
    edge.toFront();
    edge.getSource().toFront();
    edge.getTarget().toFront();
  });
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});

graph.on('node:mouseleave', ev => {
  // 获得图上所有边实例
  const edges = graph.getEdges();
  // 遍历边,将所有边的层级放置在后方,以恢复原样
  edges.forEach(edge => {
    edge.toBack();
  });
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});
  </script>
</body>
</html>

# 显示隐藏

// 显示节点实例 nodeItem,该节点的 visible 属性值在该方法调用后被置为 true
nodeItem.show();

// 隐藏节点实例 nodeItem,该节点的 visible 属性值在该方法调用后被置为 false
nodeItem.hide();

// 显示边实例 edgeItem,该边的 visible 属性值在该方法调用后被置为 true
edgeItem.show();

// 隐藏边实例 edgeItem,该边的 visible 属性值在该方法调用后被置为 false
edgeItem.hide();
// 鼠标点击节点,隐藏该节点
graph.on('node:click', ev => {
  const node = ev.item;
  console.log('before hide(), the nodevisible = ', node.get('visible'));
  node.hide();
  graph.paint();
  console.log('after hide(), the node visible = ', node.get('visible'));
});

// 鼠标点击边,隐藏该边
graph.on('edge:click', ev => {
  const edge = ev.item;
  console.log('before hide(), the edge visible = ', edge.get('visible'));
  edge.hide();
  graph.paint();
  console.log('after hide(), the edge visible = ', edge.get('visible'));
});

// 鼠标点击画布,显示所有节点和边
graph.on('canvas:click', ev => {
  const nodes = graph.getNodes();
  const edges = graph.getEdges();
  nodes.forEach(node => {
    node.show();
  });
  edges.forEach(edge => {
    edge.show();
  });
  graph.paint();
});

# shape 和 keyShape

每一种节点和边都有一个唯一的关键图形 keyShape。keyShape 是在节点的 draw() 方法中返回的图形对象

内置节点/边配置项中的 style 属性将只体现在它的 keyShape 上。且内置节点/边的状态样式 (图实例的 nodeStateStyles / edgeStateStyles 或元素自身的 stateStyles) 也仅体现在它的 keyShape 上。

# anchorPoints

结合sourceAnchor targetAnchor更好配置

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tutorial Demo</title>
  <style type="text/css">
  	
	.g6-tooltip {
	  border: 1px solid #e2e2e2;
	  border-radius: 4px;
	  font-size: 12px;
	  color: #545454;
	  background-color: rgba(255, 255, 255, 0.9);
	  padding: 10px 8px;
	  box-shadow: rgb(174, 174, 174) 0px 0px 10px;
	}

  </style>
</head>
<body>
  <div id="mountNode"></div>
  <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.4.7/dist/g6.min.js"></script>
  <script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
  <script type="text/javascript">
// 数据源
const data = {
  nodes: [
    {
      id: 'node1',
      label: 'node1',
      x: 100,
      y: 200,
      // 该节点可选的连接点集合,该点有两个可选的连接点
      anchorPoints: [
        [0, 1],
        [0.5, 1],
      ],
      type: 'rect',
    },
    {
      id: 'node2',
      label: 'node2',
      x: 300,
      y: 400,
      // 该节点可选的连接点集合,该点有两个可选的连接点
      anchorPoints: [
        [0.5, 0],
        [1, 0.5],
      ],
      type: 'rect',
    },
  ],
  edges: [
    {
      source: 'node1',
      target: 'node2',
      // 该边连入 source 点的第 0 个 anchorPoint,
      sourceAnchor: 0,
      // 该边连入 target 点的第 0 个 anchorPoint,
      targetAnchor: 0,
      style: {
        endArrow: true,
      },
    },
    {
      source: 'node2',
      target: 'node1',
      // 该边连入 source 点的第 1 个 anchorPoint,
      sourceAnchor: 1,
      // 该边连入 source 点的第 1 个 anchorPoint,
      targetAnchor: 1,
      style: {
        endArrow: true,
      },
    },
  ],
};

// 实例化图
const graph = new G6.Graph({
  container: 'mountNode',
  groupByTypes: false,
  width: 800,
  height: 600,
  // 为方便演示,加粗边
  defaultEdge: {
    style: {
      lineWidth: 2,
    },
  },
});



// 读取数据
graph.data(data);
// 渲染图
graph.render();
// const nodes = graph.getNodes();
// // 遍历节点实例,将所有节点提前。
// nodes.forEach(node => {
//   node.toFront();
// });
// // 更改层级后需要重新绘制图
// graph.paint();


// 鼠标进入节点事件
graph.on('edge:mouseenter', ev => {
  // 获得鼠标当前目标边
  const edge = ev.item;
  // 该边的起始点
  const source = edge.getSource();
  // 该边的结束点
  const target = edge.getTarget();
  // 先将边提前,再将端点提前。这样该边两个端点还是在该边上层,较符合常规。
  edge.toFront();
  source.toFront();
  target.toFront();
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});

graph.on('edge:mouseleave', ev => {
  // 获得图上所有边实例
  const edges = graph.getEdges();
  // 遍历边,将所有边的层级放置在后方,以恢复原样
  edges.forEach(edge => {
    edge.toBack();
  });
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});

graph.on('node:mouseenter', ev => {
  // 获得鼠标当前目标节点
  const node = ev.item;
  // 获取该节点的所有相关边
  const edges = node.getEdges();
  // 遍历相关边,将所有相关边提前,再将相关边的两个端点提前,以保证相关边的端点在边的上方常规效果
  edges.forEach(edge => {
    edge.toFront();
    edge.getSource().toFront();
    edge.getTarget().toFront();
  });
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});

graph.on('node:mouseleave', ev => {
  // 获得图上所有边实例
  const edges = graph.getEdges();
  // 遍历边,将所有边的层级放置在后方,以恢复原样
  edges.forEach(edge => {
    edge.toBack();
  });
  // 注意:必须调用以根据新的层级顺序重绘
  graph.paint();
});
  </script>
</body>
</html>

# vue中体验G6

<template>
  <div class="hello" ref="hello">
    <div id="left">1</div>
	<div id="canvas"></div>
	<div id="right">3</div>
  </div>
</template>

<script>
import G6 from"@antv/G6"
export default {
  name: 'HelloWorld',
  data(){
	  return{
		  graph:null,
		  data:null,
		
	  }
  },
  mounted(){
	const width = this.$refs.hello.clientWidth ;
	const height = this.$refs.hello.clientHeight;
	console.log(width)
	console.log("-----")
	this.data= {
		  // 点集
		  nodes: [
			{
			  id: 'node1', // String,该节点存在则必须,节点的唯一标识
			  x: 100, // Number,可选,节点位置的 x 值
			  y: 200, // Number,可选,节点位置的 y 值
			},
			{
			  id: 'node2', // String,该节点存在则必须,节点的唯一标识
			  x: 300, // Number,可选,节点位置的 x 值
			  y: 200, // Number,可选,节点位置的 y 值
			},
		  ],
		  // 边集
		  edges: [
			{
			  source: 'node1', // String,必须,起始点 id
			  target: 'node2', // String,必须,目标点 id
			},
		  ]
	}
	
	const minimap = new G6.Minimap({
	  size: [100, 100],
	  className: 'minimap',
	 
	});
	const grid = new G6.Grid();
	this.graph=new G6.Graph({
		container:"canvas",
		width:width-400,
		height:height,
		plugins: [minimap,grid],
		        // 节点默认配置
        defaultNode: {
          labelCfg: {
            style: {
              fill: '#fff',
            },
          },
        },
        // 边默认配置
        defaultEdge: {
          labelCfg: {
            autoRotate: true,
          },
        },
        // 节点在各状态下的样式
        nodeStateStyles: {
          // hover 状态为 true 时的样式
          hover: {
            fill: 'lightsteelblue',
          },
          // click 状态为 true 时的样式
          click: {
            stroke: '#000',
            lineWidth: 3,
          },
        },
        // 边在各状态下的样式
        edgeStateStyles: {
          // click 状态为 true 时的样式
          click: {
            stroke: 'steelblue',
          },
        },
        // 布局
        layout: {
          type: 'force',
          linkDistance: 100,
          preventOverlap: true,
          nodeStrength: -30,
          edgeStrength: 0.1,
        },
        // 内置交互
        modes: {
          default: [
			'drag-canvas',
			'zoom-canvas',
			'drag-node',
			{
				type: 'tooltip', // 提示框
				formatText(model) {
				  // 提示框文本内容
				 
				  const text = 'label: ' + model.label + '<br/> class: ' + model.class;
				  return text;
				}
			}
		  ],
        },
		
	})
	
	let remoteData = null;
	const response = fetch(
          'https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json',
        ).then(res=>{
		
			return  res.json()
			
		}).then((res)=>{
			remoteData=res;
			console.log(res)
			 const nodes = remoteData.nodes;
			const edges = remoteData.edges;
			nodes.forEach(node => {
			  if (!node.style) {
			    node.style = {};
			  }
			  node.style.lineWidth = 1;
			  node.style.stroke = '#666';
			  node.style.fill = 'steelblue';
			  switch (node.class) {
			    case 'c0': {
			      node.shape = 'circle';
			      node.size = 30;
			      break;
			    }
			    case 'c1': {
			      node.shape = 'rect';
			      node.size = [35, 20];
			      break;
			    }
			    case 'c2': {
			      node.shape = 'ellipse';
			      node.size = [35, 20];
			      break;
			    }
			  }
			});
			edges.forEach(edge => {
			  if (!edge.style) {
			    edge.style = {};
			  }
			  edge.style.lineWidth = edge.weight;
			  edge.style.opacity = 0.6;
			  edge.style.stroke = 'grey';
			});
			
				
				
			this.graph.data(remoteData)
			this.graph.render()
			       // 监听鼠标进入节点
			this.graph.on('node:mouseenter', e => {
			  const nodeItem = e.item;
			  // 设置目标节点的 hover 状态 为 true
			  this.graph.setItemState(nodeItem, 'hover', true);
			});
			// 监听鼠标离开节点
			this.graph.on('node:mouseleave', e => {
			  const nodeItem = e.item;
			  // 设置目标节点的 hover 状态 false
			  this.graph.setItemState(nodeItem, 'hover', false);
			});
			// 监听鼠标点击节点
			this.graph.on('node:click', e => {
			  // 先将所有当前有 click 状态的节点的 click 状态置为 false
			  const clickNodes = this.graph.findAllByState('node', 'click');
			  clickNodes.forEach(cn => {
			    this.graph.setItemState(cn, 'click', false);
			  });
			  const nodeItem = e.item;
			  // 设置目标节点的 click 状态 为 true
			  this.graph.setItemState(nodeItem, 'click', true);
			});
			// 监听鼠标点击节点
			this.graph.on('edge:click', e => {
			  // 先将所有当前有 click 状态的边的 click 状态置为 false
			  const clickEdges = this.graph.findAllByState('edge', 'click');
			  clickEdges.forEach(ce => {
			    this.graph.setItemState(ce, 'click', false);
			  });
			  const edgeItem = e.item;
			  // 设置目标边的 click 状态 为 true
			  this.graph.setItemState(edgeItem, 'click', true);
			});
		})
        


		
	console.log(this.graph)
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="stylus">
.hello
	display flex
	height 100%
	font-size 0
	// overflow-y hidden
	#left 
		width 200px
		border-right 1px solid #F2F2F2
		height 100%
		font-size 12px
	#right
		width 200px 
		border-left 1px solid #F2F2F2
		height 100%
		font-size 12px
	#canvas 
		flex:1
		height 100%
		position relative
		



</style>
<style>
	.minimap{
		position:fixed;
		top:0;
		left:200px;
		
	}
	.g6-tooltip {
      border: 1px solid #e2e2e2;
      border-radius: 4px;
      font-size: 12px;
      color: #545454;
      background-color: rgba(255, 255, 255, 0.9);
      padding: 10px 8px;
      box-shadow: rgb(174, 174, 174) 0px 0px 10px;
    }
</style>

警告

  • shape会被废弃,以后版本需要改成type
  • 配置minimap时写在stylus里不生效,只好写在style里
  • 给容器加了个定位relative,否则位置有问题

更多参见官方文档官网地址 (opens new window)

最后更新: 5/15/2020, 2:42:42 PM