GoJS學習筆記

目錄

GoJS 和 GO 語言沒有關係,它是一個用來建立交互式圖表的 JavaScript 庫。
javascript

基礎概念

GraphObject 是全部圖形是抽象基類,基本上 GoJS 中,萬物皆 GraphObject。html

Panel 有不一樣的類型,每一個類型表示一種佈局,經過不一樣的座標系統排列。vue

注意,GoJS 中的 x 軸水平向右,y 軸垂直向下。java

包括:node

  • Panel.Position 創建座標系,經過指定座標對絕對位置排序。
  • Panel.Vertical & Panel.Horizontal 顧名思義,分別在垂直和水平的線性排列
  • Panel.Auto 調整主元素的大小以適應 Panel 中的其餘元素。
  • Panel.Spot 經過 GraphObject.alignment 屬性指定其餘元素相對於主元素的位置。
  • Panel.Table 以表格的方式排列元素,經過指定 row 和 col 以及相關信息指定元素位置。
  • Panel.TableRow & Panel.TableColumn 只能在 Panel.Table 中使用,以將元素集合組織爲表格中的行或列。
  • Panel.Viewbox 用於自動調整 ** 單個元素 ** 的大小以適合面板的可用區域。
  • Panel.Grid 僅用於繪製常規的線條圖案。元素必須是用於描述重複行的形狀。
  • Panel.Link 僅供 Link 部件和 Link Adornments 使用。
  • Panel.Graduated 用於沿主 Shape 元素繪製常規刻度線和文本。

Part 以及他的繼承元素 Node 和 Link 等能夠直接被加到 diagram 中(經過 Diagram.add)。其餘的元素要做爲 Part 的子元素。api

Node 能夠被 Link 鏈接起來。每個 Node 都有一個 key,用來惟一標識該 Node。link 有 from 和 to 屬性,用來表示該 Link 鏈接了哪兩個邊。數組

Group 是一個 Node,能夠包含一組 Nodes 和 Links。函數

Shape 表示一個幾何圖形。可使用 GoJS 中定義好的一些圖形,如 「Rectangle」 也能夠自定義圖形的形狀。經過 fill 和 stroke 等屬性決定圖形的顯示。佈局

TextBlock 用來顯示文本。字體屬性和 CSS 相同 font-style font-variant font-weight font-size font-family。也能夠定義 stroke 等屬性。字體

Picture 用來展現圖片。

開始繪製圖形

1. 經過代碼構建圖形

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://unpkg.com/gojs/release/go.js"></script>
</head>
<body>
    <div id="myDiagramDiv" style="border: solid 1px blue; width:400px; height:150px"></div>
    <script>
      // 建立圖
      var diagram = new go.Diagram("myDiagramDiv");
      // 建立節點 節點中元素的排列方式是 Panel.Auto
      var node = new go.Node(go.Panel.Auto);
      // 建立圖形
      var shape = new go.Shape();
      // 定義圖形屬性
      shape.figure = "RoundedRectangle";
      shape.fill = "lightblue";
      // 將圖形加到節點
      node.add(shape);
      // 建立一個文本
      var textblock = new go.TextBlock();
      // 定義文本屬性
      textblock.text = "Hello!";
      textblock.margin = 5;
      // 文本加到節點
      node.add(textblock);
      // 將節點加到圖
      diagram.add(node);
    </script>
</body>
</html>

2. 經過 GraphObject.make 構建圖形

GraphObject.make 是一個神奇的函數,詳見 GraphObject.make,能夠用來建立各類 GraphObject 元素,同時定義元素的屬性。能夠嵌套定義多個元素。

上面代碼也能夠寫爲下面的方式(由於 go.GraphObject.make 使用較多,因此官網建議命名爲 $ 方便使用,你固然也能夠起其餘的名字)

var diagram = new go.Diagram("myDiagramDiv");
var $ = go.GraphObject.make;
diagram.add(
    $(go.Node, go.Panel.Auto,
        $(go.Shape,
            { figure: "RoundedRectangle", fill: "lightblue" }),
        $(go.TextBlock,
            { text: "Hello!", margin: 5 })
    ));

好處一方面是代碼量減小了,另外一方面若是給元素賦值了錯誤的屬性,make 函數會報出錯誤。

例如,若是 text 寫錯爲 test,會在控制檯看到報錯:

Uncaught Error: Trying to set undefined property "test" on object: TextBlock("")

3. 使用 Model 和 Templates 建立圖形

雖然第二種方式很簡單,可是若是要加不少的 Node,而不一樣的 Node 之間結構相同,經過上面的方式,就須要 add 好屢次。若是能定義一個 Node 的模板,而後經過指定參數來定義節點,就會方便不少。

這就相似定義一個類,之後只須要經過 new Something(p1, p2...) 來將建立一類對象。

舉例,

var diagram = new go.Diagram("myDiagramDiv");
var $ = go.GraphObject.make;
diagram.nodeTemplate =  // 定義模板
    $(go.Node, "Auto",
    $(go.Shape,
        { figure: "RoundedRectangle", fill: "white" }),
    $(go.TextBlock,
        { text: "hello!", margin: 5 })
    );
var nodeDataArray = [
    { key: "Alpha" },
    { key: "Beta" }
];
var linkDataArray = [
    { from: "Alpha", to: "Beta" }
];
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);

經過 go.GraphLinksModel 來建立一個圖須要分別指定 Node 和 Link 的集合。定義好模板(diagram.nodeTemplate)後,只須要爲 diagram.model 傳入 nodeDataArray,數組中每個元素都在圖中對應一個節點和 linkDataArray,對應每一條邊。

若是 Node 的結構相同,只是某幾個屬性不一樣,也能夠在模板中定義變量。變量經過 go.Binding 來定義。

var diagram = new go.Diagram("myDiagramDiv");
var $ = go.GraphObject.make;
diagram.nodeTemplate =  // 定義模板
    $(go.Node, "Auto",
    $(go.Shape,
        { figure: "RoundedRectangle", fill: "white" }, // white 做爲 fill 的默認屬性
        new go.Binding('fill', 'myFill') // 在 model 的 nodes 中經過 myFill 屬性來指定 Node 的 fill 屬性
    ),
    $(go.TextBlock,
        { text: "hello!", margin: 5 })
    );
var nodeDataArray = [
    { key: "Alpha" }, // 默認白色節點
    { key: "Beta", myFill: 'green' } // 綠色節點
];
var linkDataArray = [
    { from: "Alpha", to: "Beta" }
];
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);

獲取圖形數據

獲取全部 Node、Link

經過 diagram.model.nodeDataArray 會得到全部節點的集合。

[{"key":"Alpha","__gohashid":408},{"key":"Beta","myFill":"green","__gohashid":409}]

會發現節點的屬性除了用戶賦值的之外,還有一個 __gohashid ,這個是 GoJS 維護的一個屬性,不須要去管。

經過 diagram.model.linkDataArray 會得到全部邊的集合。

經過 diagram.nodes 得到的是全部 Nodes 和 Groups 的迭代器 Iterator<Node>。遍歷迭代器:

for (var it = diagram.nodes; it.next(); ) {
    var node = it.value;
    console.log(node);
}

diagram.links 同理。

注意,經過 diagram 得到的節點和 model 中的不一樣,這樣得到的節點包含不少圖中的其餘信息,好比對於邊,包含相連的節點信息等。

diagram.model.toJSON()

能夠經過 diagram.model.toJSON() 獲取圖形相關數據,其中下劃線開頭的屬性會被忽略,天然也會忽略 __gohashid ,因此起本身的屬性名時,不要如下劃線開頭。

> diagram.model.toJSON()
< "{ "class": "GraphLinksModel",
      "nodeDataArray": [ 
        {"key":"Alpha"},
        {"key":"Beta", "myFill":"green"}
       ],
      "linkDataArray": [ {"from":"Alpha", "to":"Beta"} ]
   }"

使用 diagram.model = go.Model.fromJson(model); 可使用 model 字符串加載圖。

獲取指定的 Node,Link

獲取指定 key 的 Node: findNodeDataForKey

> diagram.model.findNodeDataForKey('Alpha')
< {key: "Alpha", __gohashid: 408}

獲取指定 key 的 Link findLinkDataForKey,默認 GoJS 中的 Link 是不會被賦值一個惟一的 key 的,除非設置 linkKeyProperty

也能夠經過 diagram 查找節點。

> diagram.findNodeForKey('Alpha')
< V {__gohashid: 457, G: 4194307, lb: 1, bg: null, Ua: "", …}

> diagram.findNodeForKey('Alpha').data === diagram.model.findNodeDataForKey('Alpha')
< true

在 diagram 中查找邊 diagram.findLinkForData,不過查找的 data 要指定全部的屬性,包括 __gohashid

> diagram.findLinkForData({from: "Alpha", to: "Beta",__gohashid: 411})
< S {__gohashid: 469, G: 4194307, lb: 1, bg: null, Ua: "", …}

> link = diagram.findLinkForData(diagram.model.linkDataArray[0])
< S {__gohashid: 469, G: 4194307, lb: 1, bg: null, Ua: "", …}

> link.data
< {from: "Alpha", to: "Beta", __gohashid: 411}

> link.fromNode
< V {__gohashid: 457, G: 4194307, lb: 1, bg: null, Ua: "", …}

獲取選擇元素信息

diagram.selection 是一個只讀屬性,返回被選中元素(包括節點和邊)集合。

得到選中個數 diagram.selection.size

獲取第一個選中的元素,diagram.selection.first()

修改圖形

修改節點屬性

直接修改 model 中的屬性值不會使圖形發生改變的,要經過 setDataProperty 進行修改。

var data = myDiagram.model.findNodeDataForKey("Alpha");
// 直接修改不生效
if (data !== null) data.color = "red";
// 經過 diagram.model.setDataProperty 修改才能夠
diagram.model.setDataProperty(data, 'myFill', 'purple');

選中元素

經過代碼指定選中元素。

var node = diagram.findNodeForKey('Alpha');
// 會清除當前選中並選中 node
diagram.select(node);

刪除、添加節點和邊

var node = { key: 'addNode', myFill: 'tomato' };
// 添加節點
diagram.model.addNodeData(node);
// 添加邊 Alpha -> addNode
diagram.model.addLinkData({from:'Alpha', to: 'addNode'});
// 刪除節點
diagram.model.removeNodeData(node);

事件

Model 和 Diagram 都會產生事件。因此能夠經過 Model.addChangedListenerDiagram.addChangedListener 添加事件監聽器。經過 removeChangedListener 刪除事件監聽。

let listener = function(changedEvent) {
    // do something...
}
// 添加監聽器
diagram.addModelChangedListener(listener);
// 移除監聽器
diagram.removeModelChangedListener(listener);

經過 Model.setDataProperty 修改元素的屬性,圖形的結構不會發生變化 changedEvent.modelChange 會是一個空字符串。

diagram.addModelChangedListener(function(changedEvent) {
    // 修改的元素對象(修改後) 修改屬性 修改以前的值 修改以後的值
    if (changedEvent.modelChange === '') {
        console.log(changedEvent.object, changedEvent.propertyName, changedEvent.oldValue, changedEvent.newValue);
    }
});

其餘狀況下 changedEvent.modelChange 會是下面的字符串之一:

  • "nodeDataArray", 修改 Model.nodeDataArray 包括 diagram.model.nodeDataArray = [...]Model.addNodeDataModel.removeNodeData
  • "nodeCategory", 調用 Model.setCategoryForNodeData
  • "nodeGroupKey", GraphLinksModel.setGroupKeyForNodeData
  • "linkDataArray", 修改 GraphLinksModel.linkDataArray,包括 diagram.model.nodeDataArray = [...]GraphLinksModel.addLinkDataGraphLinksModel.removeLinkData
  • "linkFromKey", 調用 GraphLinksModel.setFromKeyForLinkData
  • "linkToKey", 調用 GraphLinksModel.setToKeyForLinkData
  • "linkFromPortId", 調用 GraphLinksModel.setFromPortIdForLinkData
  • "linkToPortId", 調用 GraphLinksModel.setToPortIdForLinkData
  • "linkLabelKeys", 調用 GraphLinksModel.setLabelKeysForLinkDataGraphLinksModel.addLabelKeyForLinkDataGraphLinksModel.removeLabelKeyForLinkData
  • "linkCategory", 調用 GraphLinksModel.setCategoryForLinkData
  • "nodeParentKey", 調用 TreeModel.setParentKeyForNodeData
  • "parentLinkCategory", 調用 TreeModel.setParentLinkCategoryForNodeData

事務相關的事務, ChangedEvent.propertyName 會是如下的值。它們的 changedEvent.modelChange 也是一個空字符串。

  • "StartingFirstTransaction"
  • "StartedTransaction"
  • "CommittingTransaction"
  • "CommittedTransaction"
  • "RolledBackTransaction"
  • "StartingUndo"
  • "FinishedUndo"
  • "StartingRedo"
  • "FinishedRedo"

能夠經過 isTransactionFinished 判斷事件是不是結束。

diagram.addModelChangedListener(function(evt) {
    if (evt.isTransactionFinished) saveModel(evt.model);
});

Transactions

由於 GoJS 有 undo 和 redo 的功能,因此在撤銷和恢復時,要保證單步操做一系列修改的完整性。

可是原則上,每次使用代碼來對圖形進行修改,都應該用事務包裹起來,即便不開啓 undo/redo 功能。

開啓 undo & redo 功能 Ctrl-Z(撤銷)/ Ctrl-Y(恢復)

diagram.model.undoManager.isEnabled = true;
// 或
diagram =
    $(go.Diagram, "myDiagramDiv",
        {
            "undoManager.isEnabled": true  // undo & redo
        });

使用事物:

diagram.commit(function(d) {
    // ....
}, "do a transaction");

Template Maps

上面的節點模板都只有一種,經過 diagram.nodeTemplate 來定義。當一個圖形中但願有多種表現形式的節點時變不夠用了。這時可使用 myDiagram.nodeTemplateMap 來定義多種模板,並在使用時經過 category 指定。

var template1 = 
    $(go.Node, "Auto",
        $(go.Shape,
            { figure: "RoundedRectangle", fill: "white" }),
        $(go.TextBlock,
            { text: "hello!", margin: 5 },
            new go.Binding('text', 'text')
        ));

var template2 =
    $(go.Node, "Auto",
        $(go.Shape, "RoundedRectangle",
            new go.Binding("fill", "color")),
        $(go.Panel, "Table",
            { defaultAlignment: go.Spot.Left },
            $(go.TextBlock, { row: 0, column: 0, columnSpan: 2, font: "bold 12pt sans-serif" },
            new go.Binding("text", "key")),
            $(go.TextBlock, { row: 1, column: 0 }, "Description:"),
            $(go.TextBlock, { row: 1, column: 1 }, new go.Binding("text", "desc")),
            $(go.TextBlock, { row: 2, column: 0 }, "Color:"),
            $(go.TextBlock, { row: 2, column: 1 }, new go.Binding("text", "color"))
        )
    );

// 設置 category 爲空字符串 則爲不指定 category 時的默認圖形
diagram.nodeTemplateMap.add('', template1);
// category: detailtemplate
diagram.nodeTemplateMap.add('detailtemplate', template2);

/* 或者定義一個 go.Map 並賦值給 diagram.nodeTemplateMap
    var templmap = new go.Map();
    templmap.add("", template1);
    templmap.add("detailtemplate", template2);
    diagram.nodeTemplateMap = templmap;
*/

var nodeDataArray = [
    { key: "Alpha", text: 'Alpha' },
    { key: "Beta", text: 'Beta', color: 'pink', desc: 'desc', category: 'detailtemplate' }
];
var linkDataArray = [
    { from: "Alpha", to: "Beta" }
];
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);

Palette Diagrams

建立 go.Palette 來建立圖形模板,能夠經過拖拽的方式快速生成一系列相同的圖案。

在Vue中使用GOJS

官網例子很清晰 不須要贅述

https://gojs.net/latest/samples/vue.html

相關文章
相關標籤/搜索