共计 7831 个字符,预计需要花费 20 分钟才能阅读完成。
图
// 创立 G6 图实例
const graph = new G6.Graph({
container: 'mountNode', // 指定图画布的容器 id,与第 9 行的容器对应
// 画布宽高
width: 800,
height: 500,
});
// 读取数据
graph.data(data);
// 渲染图
graph.render();
// 监听
graph.on()
Graph 对象的生命周期为:初始化 —> 加载数据 —> 渲染 —> 更新 —> 销毁。
必要配置项
下面代码中实例化 Graph 的局部应用了三个必要的配置项:
container
width
、height
罕用配置项
应用 canvas 或 svg 渲染
renderer
自适应画布
fitView
fitViewPadding
fitCenter
全局元素配置
defaultNode
defaultEdge
nodeStateStyles
edgeStateStyles
布局相干
layout
交互行为相干
modes
动画相干
animate
animateCfg
插件
plugins
图形
每个图元素由图形(Shape)组成,且都会有本人的惟一要害图形(keyShape)。
图形 Shape
- circle:圆;
- rect:矩形;
- ellipse:椭圆;
- polygon:多边形;
- fan:扇形;
- image:图片;
- marker:标记;
- path:门路;
- text:文本;
- dom(svg):DOM
各图形 Shape 的通用办法
attr(name)
获取实例的属性值。
attr(name, value)
更新实例的单个绘图属性。
attr({…})
批量更新实例绘图属性。
KeyShape
代表元素的图形
group
- addGroup(cfgs)
- addShape(type, cfgs)
变换
- 获取以后矩阵:getMatrix();
- 设置矩阵:setMatrix(matrix) 或 attr(‘matrix’, matrix);
- 重置矩阵:resetMatrix()。
图元素
图的元素(Item)蕴含图上的节点 Node、边 Edge 和 Combo 三大类。
- 款式属性,通过
style
字段对象进行配置,和元素的要害图形相干,例如fill
,stroke
。 - 其余属性,例如
id
、type
,不能在元素状态扭转是进行扭转,可通过 graph.updateItem 进行手动更新。
节点
G6 的内置节点包含 circle,rect,ellipse,diamond,triangle,star,image,modelRect。这些内置节点的默认款式别离如下图所示。
定义形式
// 1
defaultNode: {
type: 'circle',
// 其余配置
}
//2
graph.node((node) => {
return {
id: node.id,
type: 'rect',
style: {fill: 'blue',},
};
});
graph.data(data);
graph.render();
//3
const data = {
nodes: [
{
id: 'node_circle',
x: 100,
y: 100,
type: 'circle',
label: 'circle',
},]
}
自定义
G6.registerNode(
'nodeName',
{
options: {style: {},
stateStyles: {hover: {},
selected: {},},
},
/**
* 绘制节点,蕴含文本
* @param {Object} cfg 节点的配置项
* @param {G.Group} group 图形分组,节点中图形对象的容器
* @return {G.Shape} 返回一个绘制的图形作为 keyShape,通过 node.get('keyShape') 能够获取。* 对于 keyShape 可参考文档 外围概念 - 节点 / 边 /Combo- 图形 Shape 与 keyShape
*/
draw(cfg, group) {},
/**
* 绘制后的附加操作,默认没有任何操作
* @param {Object} cfg 节点的配置项
* @param {G.Group} group 图形分组,节点中图形对象的容器
*/
afterDraw(cfg, group) {},
/**
* 更新节点,蕴含文本
* @override
* @param {Object} cfg 节点的配置项
* @param {Node} node 节点
*/
update(cfg, node) {},
/**
* 更新节点后的操作,个别同 afterDraw 配合应用
* @override
* @param {Object} cfg 节点的配置项
* @param {Node} node 节点
*/
afterUpdate(cfg, node) {},
/**
* 响应节点的状态变动。* 在须要应用动画来响应状态变动时须要被复写,其余款式的响应参见下文提及的 [配置状态款式] 文档
* @param {String} name 状态名称
* @param {Object} value 状态值
* @param {Node} node 节点
*/
setState(name, value, node) {},
/**
* 获取锚点(相干边的连入点)* @param {Object} cfg 节点的配置项
* @return {Array|null} 锚点(相干边的连入点)的数组, 如果为 null,则没有控制点
*/
getAnchorPoints(cfg) {},},
// 继承内置节点类型的名字,例如基类 'single-node',或 'circle', 'rect' 等
// 当不指定该参数则代表不继承任何内置节点类型
extendedNodeName,
);
连贯形式
// 接入点
anchorPoints: [[0, 1],
[0.5, 1],
],
jsx 写法
<[group|shape] [key]="value" style={{[key]: value }}>
<[more tag] /> ...
<text>value</text>
</[group|shape]>
边
- line:直线,不反对控制点;
- polyline:折线,反对多个控制点;
- arc:圆弧线;
- quadratic:二阶贝塞尔曲线;
- cubic:三阶贝塞尔曲线;
- cubic-vertical:垂直方向的三阶贝塞尔曲线,不思考用户从内部传入的控制点;
- cubic-horizontal:程度方向的三阶贝塞尔曲线,不思考用户从内部传入的控制点;
- loop:自环。
定义形式: 与节点相似
箭头:
// 默认
style: {
endArrow: true,
startArrow: true
}
// 内置 6 种
endArrow: {
// 应用内置箭头门路函数,参数为箭头的 宽度、长度、偏移量(默认为 0,与 d 对应)path: G6.Arrow.triangle(10, 20, 25),
d: 25
}
// 自定义箭头
// 只有内置箭头和自定义箭头能够配置款式
style: {
endArrow: {
path: 'M 0,0 L 20,10 L 20,-10 Z',
d: 5,
fill: '#f00',
stroke: '#0f0',
opacity: 0.5,
lineWidth: 3,
// ...
},
}
自定义: 同节点
combo
G6 的内置 Combo 包含 circle 和 rect 两种类型
对于相熟图可视化类库的用户来说,节点分组是十分实用的一个性能
G6 曾经存在一个节点分组 Node Group 性能,但它的机制无奈反对一些较简单的性能,例如:带有节点分组的图布局、自定义 Combo、嵌套节点分组的平均 padding、节点与分组的边、分组与分组的边、空的节点分组等
{
nodes: [
{
id: 'node1',
comboId: 'comboA' // node1 属于 comboA
},
{
id: 'node2',
comboId: 'comboB' // node2 属于 comboB
},
{id: 'node3' // node3 不属于任何 combo},
// ...
],
edges: [// ...],
combos: [
{ // 定义 comboA
id: 'comboA',
label: 'A',
parentId: 'comboC'
},
{ // 定义 comboB
id: 'comboB',
parentId: 'comboB'
},
{ // 定义 comboC,这是一个空的 combo
id: 'comboC'
},
// ...
]
}
其余内容: 相似与节点
高级款式
背景
defaultNode: {
position: 'left',
style: {
background: {
fill: '#ffffff',
stroke: 'green',
padding: [3, 2, 3, 2],
radius: 2,
lineWidth: 3,
},
},
三种形式更新文本款式
// 1. 实例化默认
defaultNode: {
type: 'node',
labelCfg: {
style: {
fill: '#fff',
fontSize: 14,
},
},
},
// 2. 数据指定
const data = {
nodes: [
{
id: 'node1',
label: 'node1',
labelCfg: {
style: {
fill: '#fff',
fontSize: 12,
},
},
},
],
};
// 3.update/updateItem
graph.updateItem(node, {
// 节点的款式
style: {stroke: 'blue',},
// 节点上文本的款式
labelCfg: {
style: {
fill: '#fff',
fontSize: 12,
},
},
});
渐变色 / 纹理
操作
更新款式
更新节点边: 三种形式
层级
所有节点会绘制在所有边的下层
先绘制图形在后绘制图形后边
toFront()
与 toBack()
显示 / 暗藏
show()/hide()
多条边
自定义边 edgeType
锁定 / 解锁
lock()
、unlock()
和 hasLocked()
不可拖动
不可缩放
图布局
个别布局
- Random Layout:随机布局;
- Force Layout:G6 4.0 反对的经典力导向布局,反对 GPU 并行计算;
- Force Layout:援用 d3 的经典力导向布局;
- Fruchterman Layout:Fruchterman 布局,一种力导布局;
- Circular Layout:环形布局;
- Radial Layout:辐射状布局;
- MDS Layout:高维数据降维算法布局;
- Dagre Layout:档次布局;
- Concentric Layout:同心圆布局;
- Grid Layout:网格布局;
- Combo Force Layout:_V3.5 新增。_实用于带有 combo 图的力导向布局,举荐有 combo 的图应用该布局。
树图
- CompactBox Layout:紧凑树布局;
- Dendrogram Layout:树状布局(叶子节点布局对齐到同一层);
- Indented Layout:缩进布局;
- Mindmap Layout:脑图布局。
布局切换
updateLayout(params)
:布局办法或参数的切换;
graph.updateLayout({
type: 'force', // 布局名称
preventOverlap: true, // 布局参数,是否容许重叠
nodeSize: 40, // 布局参数,节点大小,用于判断节点是否重叠
linkDistance: 100, // 布局参数,边长
});
* `changeData()`:数据的切换。graph.changeData(data2);
子图
子图布局独立与全局布局的思路,与 graph 不挂钩,间接应用实例化布局办法的形式,灌入子图数据,通过布局将地位写到相应数据中。这种机制还可供内部的全局布局应用,即便不必 G6 渲染,也能够计算节点布局后的地位
// 实例化布局
const subgraphLayout = new G6.Layout['force']({center: [500, 450],
});
// 初始化布局,灌入子图数据
subgraphLayout.init({
nodes: subGraphNodes,
edges: subGraphEdges,
});
// 执行布局
subgraphLayout.execute();
// 图实例依据数据更新节点地位
graph.positionsAnimate();
webworker
在大规模图可视化中,布局算法往往须要较大的计算量。
workerEnabled: true, // 开启 Web-Worker
- 树图不反对 Web-Worker 机制;
- 子图布局机制暂不反对 Web-Worker 机制。
- 应用会造成交互延时须要留神
自定义布局
getDefaultCfg() {return {};
},
/**
* 初始化
* @param {object} data 数据
*/
init(data) {},
/**
* 执行布局
*/
execute() {},
/**
* 依据传入的数据进行布局
* @param {object} data 数据
*/
layout(data) {},
/**
* 更新布局配置,但不执行布局
* @param {object} cfg 须要更新的配置项
*/
updateCfg(cfg) {},
/**
* 销毁
*/
destroy() {},
});
布局预测
import {GraphLayoutPredict} from '@antv/vis-predict-engine'
const {predictLayout, confidence} = await GraphLayoutPredict.predict(data);
const graph = new G6.Graph({
// 省略其余配置
layout: {type: predictLayout}
})
交互与事件
监听 / 绑定
- 画布、图形档次的事件,
mousedown
,mouseup
,click
,mouseenter
,mouseleave
等; - 节点 / 边 上的事件,
node:mousedown
,edge:click
等,以type:eventName
为事件名称; -
机会事件:
- 节点 / 边增删改时的事件, 例如:
beforeadditem
,afteradditem
等; - 节点 / 边状态扭转时的事件:
beforerefreshitem
与afterrefreshitem
; - 布局机会:
beforelayout
与afterlayout
。
- 节点 / 边增删改时的事件, 例如:
graph.on('click', (ev) => {
const shape = ev.target;
const item = ev.item;
if (item) {const type = item.getType();
}
});
graph.on('node:click', (ev) => {
const shape = ev.target;
const node = ev.item;
});
内置 behavior
ehavior 是 G6 提供的定义图上交互事件的机制。
G6 目前共提供了以下 14 个内置的 Behavior。
drag-combo
collapse-expand-combo
drag-canvas
zoom-canvas
drag-node
click-select
tooltip
edge-tooltip
activate-relations
brush-select
lasso-select
collapse-expand
create-edge
shortcuts-call
自定义交互 Behavior
在交互行为上,G6 次要思考了三个场景:
- 展现关系数据;
- 可视化建模;
- 图剖析。
在这些场景中只有用户可能无奈一眼看清楚所有须要的信息,都须要进行交互,例如:
- 图太大,须要缩放;
- 单个节点上展现的信息太少,须要通过 tooltip 显示详情;
- 对节点进行增删改查。
交互模式 Mode
- default 模式中蕴含点击选中节点行为和拖拽画布行为;
- edit 模式中蕴含点击节点弹出编辑框行为和拖拽节点行为。
modes: {
// 反对的 behavior
default: ['drag-canvas', 'zoom-canvas'],
edit: ['click-select'],
},
// 解绑目前图模式的所有事件监听;
// 生成新的 Behavior,进行事件初始化;
// 绑定新的行为对应的事件监听。
graph.setMode(‘edit’);
graph.addBehaviors
graph.removeBehaviors
状态 State
判断是否该应用 state 的准则很简略,从交互和业务两个层面来看:
- 某个交互动作要扭转节点或边的款式及属性;
- 出现给用户的内容会依据数据扭转(如 1 代表胜利,0 代表失败)。
满足上述条件其一,则应该应用 state。
在 G6 中,有两种形式配置不同状态的款式:
- 在实例化 Graph 时,通过
nodeStateStyles
和edgeStateStyles
对象定义; - 在节点 / 边数据中,在
stateStyles
对象中定义状态; - 设置状态:
setItemState
- 勾销状态:
clearItemStates
- 更新状态:
updateItem
graph.setItemState(item, stateName, stateValue)
graph.clearItemStates(item, 'selected');
// 实例化
nodeStateStyles: { },
// 数据
stateStyles: { },
//updataItem
stateStyles: {
// 批改 hover 状态下的款式
hover: {
opacity: 0.1,
// 批改 name 为 'node-label' 的子图形 hover 状态下的款式
'node-text': {stroke: 'blue',},
},
},
// 优先级
item.hasState('active');
插件 **
- Grid
- Minimap
- ImageMinimap
- Edge Bundling
- Menu
- ToolBar
- TimeBar
- Tooltip
- Fisheye
- EdgeFilterLens
// 实例化 Image Minimap 插件
const imageMinimap = new G6.ImageMinimap({
width: 200,
graphImg: 'https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*eD7nT6tmYgAAAAAAAAAAAABkARQnAQ'
});
const graph = new G6.Graph({
//... 其余配置项
plugins: [imageMinimap], // 配置 imageMinimap 插件
});
图算法
计算 nodes,edges x/y
动画
全局
// 全局
animate: true, // Boolean,切换布局时是否应用动画适度,默认为 false
graph.updateLayout(cfg) 布局的变动
graph.changeData() 数据的变动
元素
- 节点上图形的动画
- 减少带有动画的背景图形
- 节点上局部图形的旋转动画
- 圆点在沿着线静止
- 虚线静止的成果
- 线从无到有的成果
// 开始
shape.animate((ratio) => {
// 每一帧的操作,入参 ratio:这一帧的比例值(Number)。返回值:这一帧须要变动的参数集(Object)。// 先变大、再变小
const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
let radius = cfg.size;
if (isNaN(radius)) radius = radius[0];
// 返回这一帧须要变动的参数集,这里只蕴含了半径
return {r: radius / 2 + diff,};
},
{
// 动画反复
repeat: true,
duration: 3000,
easing: 'easeCubic',
},
); // 一次动画继续的时长为 3000,动画成果为 'easeCubic'
// 完结
shape.stopAnimate();