gojs 流程图框架-基础绘图(一)
gojs 是一款非常优秀的流程图绘制 js 框架, 该框架没有中文版 api, 并且网上可查阅的资料非常少, 本文旨在带领读者了解整个框架结构, 以及基本的绘制方法. 本文对技术细节不作过多描述, 并会附上 api 地址以供参考.
完成后的效果图:
源码地址: github.com/muzqi/sampl…
Step1 初始化画布
html
<div id="diagram" style="width: 1000px; height: 500px"></div>
复制代码
javascript
// [1]
const $ = go.GraphObject.make
// [2]
const diagram = $(go.Diagram, ‘diagram‘, {
// 令绘制的元素相对画布居中
‘initialContentAlignment‘: go.Spot.Center,
// 是否可撤销编辑
‘undoManager.isEnabled‘: true
})
复制代码
代码注释:
-
gojs
有两种使用方法, 一种是使用原本的go
对象, 第二种则是构造器方式创建, 即使用go.GraphObject.make
对象创建,我们将该对象赋值给$
, 当然为了避免冲突也可以是其他符号 -
$(go.Diagram, [selector], [options])
, 该方法会执行 canvas 画布的初始化操作, 同时也提供了丰富的配置项使用, 详情参考Class Diagram
Step2 编写节点模板
所谓节点模板, 系指对节点建立一个统一的样式模板(集合); 如果用过 react 或 vue 等框架的童鞋自然很了解模板的意义, 在 gojs 中也一样, 我们建立好公用模板后, 只需要数据传参即可
gojs 一共有两种方式搭建节点模板 nodeTemplate 和 nodeTemplateMap
这里只讲解 nodeTemplateMap
, 它是一个节点模板集合, 里面可以自定义丰富的节点模板 它的使用方法类似 css 的类, 定义模板时定义类名, 调用时指定该类名即可
小试牛刀
// [1]
diagram.nodeTemplateMap.add(‘templateName‘,
$(go.Node, go.Panel.Auto,
$(go.TextBlock,
{ text: ‘test‘ },
/*[2]*/new go.Binding(‘text‘, ‘text‘))
)
)
// [3]
const nodeDataArray = [
{ category: ‘templateName‘, key: ‘check‘, text: ‘审核‘ }
]
// [4]
const linkDataArray = []
// [5]
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray)
复制代码
代码注释:
1.diagram.nodeTemplateMap.add([name], [node])
- 与
ES6 Set
方法非常类似,add
即添加一个模板的意思, 第一个参数是模板的名字, 第二个参数是具体模板的配置 - 第二个参数必须传递一个
$(go.Node, [Panel], [Elements])
构造器- Panel 是指该节点的布局方式
- Elements 可以在改节点中无限嵌套元素, 文字块TextBlock 图形Shape 图片Picture 都可以作为元素添加
2.new go.Binding([origin], [target], [filter = Func])
- 这是 gojs 中的数据绑定, 使用该方法实现了模板与真实数据之间的传递
- 该方法能在任意构造器中使用
- origin: 该构造器中的属性名
- target: 需要绑定到数据集中的属性名
- filter: 过滤函数
3.定义一个节点数据集,
-
key
属性是必填的且具有唯一性, 它将运用到连接线数据集中 -
category
属性即对应了节点模板中模板的名称, 若不填, 则会默认使用第一组模板 -
text
即new go.Binding
绑定的数据
4.连接线数据集, 这里为空, 暂不讨论
5.diagram.model
决定了页面中呈现哪些元素, 我们创建一个普通连线实例 new go.GraphLinksModel
该构造函数接收两个参数, 即之前创建的 nodeDataArray
和 linkDataArray
实战演练
diagram.nodeTemplateMap.add(‘node1‘,
$(go.Node, go.Panel.Position,
// 规定该节点的宽高, 内容超出会被隐藏
{ width: 230, height: 240 },
// 绑定节点的位置属性, 用来控制节点处于画布的哪个位置
new go.Binding(‘position‘),
// 背景图片与图标
$(/*[1]*/go.Panel, /*[2]*/go.Panel.Auto,
{ position: new go.Point(0, 72) },
$(go.Picture,
{
width: 178, height: 168,
},
new go.Binding(‘source‘, ‘bgSrc‘)),
$(go.Picture,
{
width: 64, height: 64,
},
new go.Binding(‘source‘, ‘iconSrc‘))
),
// 文字背景与文本信息
$(go.Panel, go.Panel.Position,
{ position: new go.Point(50, 0) },
$(go.Picture,
{ width: 178, height: 100 },
new go.Binding(‘source‘, ‘textBgSrc‘)),
$(go.TextBlock,
{
stroke: ‘#FFF‘,
font: ‘normal bold 24px Serif‘,
position: new go.Point(80, 20)
},
new go.Binding(‘text‘))
)
)
)
const nodeDataArray = [
{
position: new go.Point(0, 0),
category: ‘node1‘,
key: ‘check‘,
bgSrc: ‘./images/circle_1.png‘,
iconSrc: ‘./images/icon-apply.png‘,
textBgSrc: ‘./images/text-bg-1.png‘,
text: ‘申请‘
}
]
复制代码
代码注释:
1.这里使用的 $(go.Panel)
你可以理解成 html 中的 div, 参见以下代码:
diagram.nodeTemplateMap.add(‘node1‘,
$(go.Node, go.Panel.Position,
{ width: 230, height: 240 },
new go.Binding(‘position‘),
// 背景图片与图标
$(go.Panel, go.Panel.Auto,
{ position: new go.Point(0, 72) },
$(go.Picture,
{
width: 178, height: 168,
},
new go.Binding(‘source‘, ‘bgSrc‘))
)
)
)
复制代码
gojs 中的 node 模板可以 ‘翻译‘ 成以下结构(如果你恰好熟悉 JSX 语法, 那就更好理解了)
<Node
className="node1"
layout="Position"
style={{ width: 230, height: 240 }}
position={position}>
<Panel
layout="Auto"
style={{ position: new go.Point(0, 72) }}>
<Picture
source={bgSrc}
style={{width: 178, height: 168}} />
</Panel>
</Node>
复制代码
我们只需要严格按照 gojs 的语法规则, 逐一嵌套, 即可绘制出任意你想要的节点模型
2.go.Panel.Auto
布局方法, 允许将 Panel 中的子元素逐一居中显示在 Node
包裹容器正中(你也可以设置偏移), 更多的布局规则, 如 Position
Vertical
Spot
等等, 请移步 Panels, 官方文档已经做了很详细的解释了
以下是当前的三个节点效果 现在就差节点之间的连接线了!
Step3 编写连接线模板
还记得之前定义的
linkDataArray
数组么? 这个数组装载所有连接线的信息 值的注意的是, 要先有 node 再有 link
与节点模板一样, 连接线模板也分 linkTemplate 和 linkTemplateMap 这里我们只介绍 linkTemplateMap
实战演练
diagram.linkTemplateMap.add(‘link1‘,
$(go.Link, // [1]
{ routing: go.Link.Normal },
new go.Binding(‘routing‘),
new go.Binding(‘fromSpot‘),
new go.Binding(‘toSpot‘),
// 线段模板
$(go.Shape, // [2]
{ strokeDashArray: [10, 20] },
new go.Binding(‘stroke‘),
new go.Binding(‘strokeWidth‘)),
// 箭头模板
$(go.Shape, // [2]
{ stroke: ‘transparent‘, strokeWidth: 0 },
new go.Binding(‘fromArrow‘),
new go.Binding(‘toArrow‘),
new go.Binding(‘scale‘, ‘arrowScale‘),
new go.Binding(‘fill‘, ‘arrowfill‘)),
// 文字块
$(go.Panel, go.Panel.Auto, // [3]
new go.Binding(‘alignmentFocus‘, ‘textPos‘),
$(go.Shape, { fill: ‘transparent‘ }, new go.Binding(‘stroke‘)),
$(go.TextBlock,
{ margin: 10 },
new go.Binding(‘stroke‘),
new go.Binding(‘text‘))
)
)
)
const linkDataArray = [
{
category: ‘link1‘,
from: ‘coor‘, to: ‘apply‘, // [4]
routing: go.Link.Orthogonal,
toArrow: ‘Standard‘,
arrowfill: ‘orange‘,
arrowScale: 2,
fromSpot: new go.Spot(0, 0.42),
toSpot: new go.Spot(0.42, 1),
stroke: ‘orange‘,
strokeWidth: 2,
text: ‘驳回‘,
textPos: new go.Spot(0, 1, -100, 20)
}
]
复制代码
代码注释:
1.go.Link
是连接线的包裹容器, 它全局为连接线定义一些属性
2.go.Link
容器中可以接收 go.Shape
构造器
- 如果只设置该构造器
stroke
相关的属性, 则表示连接线的模板 - 如果引入了
fromArrow
或toArrow
则表示设置线段两端的箭头, 官方 figure 示例
3.同样, 我们可以在线段中添加 Picture
TextBlock
Shape
Panel
等任何元素, 并且编写方式与节点模板是一致的, 只不过如果你想控制这些元素的偏移量, 你需要设置 alignmentFocus
属性
4.之前说过, nodeDataArray
中的 key 是必填的, 因为我们需要在 linkDataArray
中通过这个 key 来绝点各个节点的连接线如何相连
下期继续讲 gojs 的编辑类模板
(未完待续)