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 的編輯類别範本
(未完待續)