G6使用指南

G6 使用指南

背景

在吾来产品中有任务机器人的画布功能,我们在设计之初调研了众多库,最后挑选了一款将canvas和HTML DOM结合地不错的JSPlumb库,的的确确也很大程度上完成了功能的开发,在效果上也具有不错的体现,然而在后期,产品团队和设计团队想要对这个画布功能进行修改的时候便遭遇了极大困难,所以说,JSPlumb是一款起点和上限都不高的库。

   于是静极思变,我们看见了现在新的库G6,作为阿里团队开发维护的库,我们决定去尝试一下。

G6

G6 是一个简单、易用、完备、开源的图可视化引擎,它在高定制能力的基础上,提供了一系列设计优雅、便于使用的图可视化解决方案。能帮助开发者搭建属于自己的图可视化、图分析、或图编辑器应用。

Graphin

Graphin 取名意为 Graph Insight(图的分析洞察),是一个基于 G6 封装的 React 组件库。简单,高效,开箱即用。Graphin

由于UIbot-Observer平台的高速迭代带来了极大的压力,我便把目光放到了这个库上面,的的确确Graphin为快速开发带来了极大的便利,但是也带来不少的问题。

搭建

搭建一个graphin图表基本上需要:

1.

1
npm install @antv/graphin --save

2.

1
<Graphin data />
的确必要元素就可以这么少,当然,这么点东西肯定不能满足业务需求,大致看一看PRD中和设计提供的原型图,要满足需求需要确定整体布局、改变节点样式、改变边的样式、提供放大缩小的功能、提供全屏的功能……

确定整体布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Graphin
    data={listData}
    layout={LayoutOpt}
/>


const LayoutOpt = {
    name: 'dagre',
    options: {
     rankdir: 'TB',
     align: 'UL',
     nodesep: 200,
     ranksep: 5,
    },
};

  • 整体布局名称为 dagre ,是一种层次布局,

  • rankdir是布局的方向 Top => Bottom

  • align是对齐方式,枚举值,Up Left

  • ranksep和nodesep都是间隔值

修改节点样式

扩展API  `<Graphin/>` 组件 props.extend 配置。用于配置 Graphin 布局/NodeShape/Marker 的扩展。

想要实现一个自己满意的节点,那就不能使用Graphin提供的默认的节点样式了,需要自己手动编写一个G6对象实例,里面包括节点的名称、节点的配置等等,talk is cheap,show me the code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<Graphin
     data={listData}
     layout={LayoutOpt}

         extend={{
          nodeShape: extendNodeShape,
     }}
/>

//  基础样式配置

const defaultStyles = {
     /** 容器 */
     containerWidth: 180,
     containerHeight: 40,
     containerStroke: '#687c8a', // 边框色
     containerFill: '#687c8a', // 背景色
     /** 文本 */
     fontColor: '#FFF',
     fontColorDark: '#425b6d',
     fontSize: 14,
     /** 深色 */
     dark: '#425b6d',
};



/**
* Graphin Node 自定义样式
* @param graphin
* @param props
*/
export const extendNodeShape = (graphin: any, props: any) => {
return [
{
name: 'APPS',
render: (node: { style: any; data: any }) => {
const style = {
     ...defaultStyles,
     ...node.style,
};


return {
     shape: 'RectNode',
     shapeComponents: [
     {
          shape: 'rect',
          attrs: {
               id: 'rect-container',
               x: 0,
               y: 0,
               width: style.containerWidth,
               height: style.containerHeight,
               fill: style.containerFill,
               stroke: style.containerStroke,
               cursor: 'pointer',
               lineWidth: 2,
               radius: [4],
          },
     },
     {
          shape: 'circle',
          attrs: {
              id: 'badge',
               x: style.containerWidth,
               y: 0,
               r: style.badgeSize,
               fill: style.badgeFill,
               cursor: 'pointer',
               lineWidth: 1,
             },
     },
     {
          shape: 'text', // 这是右上角的badge 徽记
          attrs: {
                id: 'badge-text',
                x: style.containerWidth / 2,
                y: -4,
                fontSize: 10,
                cursor: 'pointer',
                fill: '#fff',
                textAlign: 'center',
                textBaseline: 'top',
          },
     },
     {
          shape: 'Marker',
          attrs: {
                id: 'node-icon',
                symbol: node.data.type,
                x: style.containerWidth / 2,
                y: style.containerWidth / 2,
                r: style.iconSize,
                fill: style.iconFill,
          },
     },
     {
          shape: 'text',
          attrs: {
                id: 'text-desc',
                text: node.data.label,
                x: style.containerWidth / 2,
                y: style.containerHeight / 2,
                cursor: 'pointer',
                fontSize: style.fontSize,
                fill: style.fontColor,
                fontWeight: 'bolder',
                fontFamily: 'Courier New',
                textAlign: 'center',
                textBaseline: 'middle',
          },
      },
],
state: {
        selected: {
                'rect-container': {
                stroke: style.containerStroke,
                fill: style.containerStroke,
                animate: {
                     attrs: {
                              lineWidth: 6,
                              shadowOffsetX: 0,
                              shadowOffsetY: 0,
                              shadowBlur: 2,
                              shadowColor: '#fff',
                              repeat: false, // 循环
                     },
                     duration: 200,
                     easing: 'easeCubic',
                     callback: null,
                     delay: 0,
                 },
                    },
                'node-icon': {
                 fill: '#fff',
                },
                badge: {
                 lineWidth: 6,
                },
        },
},

......

以上代码中,我注册了一个名为“APPS”的节点,

  • 它主体是一个矩形’rect’,起点位置[0, 0],Fill代表的是填充的背景色,Stroke代表的是边框的颜色,lineWidth代表是他的粗细;

  • 右上角会有圆形的徽标’cicle’;

  • 徽标中会有text;

  • 在主体中也有text;

  • 在选中(selected)的时候会有一个动画出现——整个节点的边框会变粗。

你想用什么节点就自己接入吧。

改变边的样式

这个就需要写在data当中了


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 在data中的设置
style: EdgeStyle,
labelCfg: FontStyle,

// 边的样式
const EdgeStyle = {
    lineWidth: 2,
    stroke: '#b3bdc5',
    endArrow: true,
    strokeOpacity: 0.7,
    shadowColor: '#b3bdc5',
    shadowBlur: 1,
};

// 字体样式
const FontStyle = {
    style: {
    fill: '#425b6d',
    lineWidth: 4,
    opacity: 0.7,
    fontSize: 14,
    fontWeight: 600,
}

都非常容易理解的参数就不一一介绍了

增加放大缩小全屏功能

这个功能听起来高大上或许非常难以实现,但是其实G6都暴露出来了api,并且Graphin都已经做好了封装,只需要:

1
2
3
4
5
6
import { Toolbar } from '@antv/graphin-components'

<Graphin>
    <Toolbar />
</Graphin>

so ez

作者: 张熠
文章链接: https://crazyoctopusdan.github.io/2020/06/09/G6%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.