1. 程式人生 > 實用技巧 >gojs 流程圖框架-基礎繪圖(一)

gojs 流程圖框架-基礎繪圖(一)

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
})
複製程式碼

程式碼註釋:

  1. gojs有兩種使用方法, 一種是使用原本的go物件, 第二種則是構造器方式建立, 即使用go.GraphObject.make物件建立,我們將該物件賦值給$, 當然為了避免衝突也可以是其他符號
  2. $(go.Diagram, [selector], [options]), 該方法會執行 canvas 畫布的初始化操作, 同時也提供了豐富的配置項使用, 詳情參考Class Diagram

Step2 編寫節點模板

所謂節點模板, 係指對節點建立一個統一的樣式模板(集合); 如果用過 react 或 vue 等框架的童鞋自然很瞭解模板的意義, 在 gojs 中也一樣, 我們建立好公用模板後, 只需要資料傳參即可

gojs 一共有兩種方式搭建節點模板nodeTemplatenodeTemplateMap

這裡只講解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])構造器

2.new go.Binding([origin], [target], [filter = Func])

  • 這是 gojs 中的資料繫結, 使用該方法實現了模板與真實資料之間的傳遞
  • 該方法能在任意構造器中使用
    • origin: 該構造器中的屬性名
    • target: 需要繫結到資料集中的屬性名
    • filter: 過濾函式

3.定義一個節點資料集,

  • key屬性是必填的且具有唯一性, 它將運用到連線線資料集中
  • category屬性即對應了節點模板中模板的名稱, 若不填, 則會預設使用第一組模板
  • textnew go.Binding繫結的資料

4.連線線資料集, 這裡為空, 暫不討論

5.diagram.model決定了頁面中呈現哪些元素, 我們建立一個普通連線例項new go.GraphLinksModel該建構函式接收兩個引數, 即之前建立的nodeDataArraylinkDataArray

實戰演練

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包裹容器正中(你也可以設定偏移), 更多的佈局規則, 如PositionVerticalSpot等等, 請移步Panels, 官方文件已經做了很詳細的解釋了

以下是當前的三個節點效果 現在就差節點之間的連線線了!


Step3 編寫連線線模板

還記得之前定義的linkDataArray陣列麼? 這個陣列裝載所有連線線的資訊 值的注意的是, 要先有 node 再有 link

與節點模板一樣, 連線線模板也分linkTemplatelinkTemplateMap這裡我們只介紹 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是連線線的包裹容器, 它全域性為連線線定義一些屬性

  • routing定義連線線的連線方式, 直角或普通等等
  • fromSpottoSpot定義連線線兩端端頭相對節點的位置
  • 還有許多可配置項, 參考Link

2.go.Link容器中可以接收go.Shape構造器

  • 如果只設置該構造器stroke相關的屬性, 則表示連線線的模板
  • 如果引入了fromArrowtoArrow則表示設定線段兩端的箭頭,官方 figure 示例

3.同樣, 我們可以線上段中新增PictureTextBlockShapePanel等任何元素, 並且編寫方式與節點模板是一致的, 只不過如果你想控制這些元素的偏移量, 你需要設定alignmentFocus屬性

4.之前說過,nodeDataArray中的 key 是必填的, 因為我們需要在linkDataArray中通過這個 key 來絕點各個節點的連線線如何相連

下期繼續講 gojs 的編輯類模板

(未完待續)