視覺化—gojs 超多超實用經驗分享(三)

Echoyya、發表於2024-07-17

目錄
  • 32.go.Palette 一排放兩個
  • 33.go.Palette 基本用法
  • 34.建立自己指向自己的連線
  • 35.設定不同的 groupTemplate 和 linkTemplate
  • 36.監聽在圖形物件 GraphObject 上的右鍵單擊
  • 37.定義節點/連線/canvas 背景上的右鍵選單
  • 38.從節點動態拉出一根連線時,判斷其方向是左還是右?
  • 39.linkTemplate routing 取值
  • 40.在移動連線時,改變所有點的位置

32.go.Palette 一排放兩個

go.Palette 是 GoJS 庫中的一個元件,用於顯示一組預定義的圖形元素,使用者可以從中選擇並將其拖放到畫布中。如果要在一排中顯示兩個 go.Palette

一、可以使用 HTML 和 CSS 來控制它們的佈局。使用display: inline-blockdiv 元素水平排列在同一行中

<style>
  #palette1,
  #palette2 {
    display: inline-block;
    width: 200px;
    height: 300px;
    border: 1px solid black;
    margin-right: 20px;
  }
</style>

<div id="palette1"></div>
<div id="palette2"></div>
<script>
  var $ = go.GraphObject.make;
  var palette1 = $(go.Palette, "palette1");
  var palette2 = $(go.Palette, "palette2");
</script>

二、(建議)還可以使用gojs自帶的屬性,完成go.Palette 自定義

  • alignment 屬性設定為 go.GridLayout.Position: 使節點從左開始佈局。
  • wrappingColumn 屬性設定為 2,以確保節點佈局為 2 列。
  • cellSizespacing 屬性, 控制節點之間的間距和大小。
const myPalette = $(go.Palette, "myPaletteDiv", {
  layout: $(go.GridLayout, {
    alignment: go.GridLayout.Position,
    wrappingColumn: 2,
    cellSize: new go.Size(100, 0),
    spacing: new go.Size(5, 5),
  }),
});

33.go.Palette 基本用法

<div id="myPaletteDiv"></div>
const myPalette = $(go.Palette, "myPaletteDiv", {
    layout: $(go.GridLayout, {
    alignment: go.GridLayout.Position,
    cellSize: new go.Size(100, 0),
    wrappingColumn: 2
})
  nodeTemplate: myDiagram.nodeTemplate,
  model: new go.GraphLinksModel([
    { key: "Alpha", text: "Alpha: Patron" },
    { key: "Beta", text: "Beta: Patron" },
    { key: "Gamma", text: "Gamma: Patron" },
  ]),
});
myPalette.groupTemplateMap.add('groupA', groupATemplate()) // 可以為多組
myPalette.model = new go.GraphLinksModel([ ]) // 屬性可以直接寫在物件裡,也可以後續修復

34.建立自己指向自己的連線

主要是在節點上設定兩個屬性,

{
  fromLinkableSelfNode: true,
  toLinkableSelfNode: true,
}

35.設定不同的 groupTemplate 和 linkTemplate

可以使用 Group 型別的 groupTemplate 屬性來設定不同的組模板。groupTemplate 屬性可以接受一個函式,該函式返回一個 Group 型別的模板。
定義了兩個不同的組模板,分別使用不同的顏色。使用時會預設讀取分組名稱。
groupTemplate

myDiagram.groupTemplateMap.add(
  "Group1",
  $(go.Group, "Auto", $(go.Shape, "Rectangle", { fill: "red" }))
);

myDiagram.groupTemplateMap.add(
  "Group2",
  $(go.Group, "Auto", $(go.Shape, "Rectangle", { fill: "green" }))
);

myDiagram.model.addNodeData({ key: 1, isGroup: true, category: "Group1" });
myDiagram.model.addNodeData({ key: 2, isGroup: true, category: "Group2" });

linkTemplate

myDiagram.linkTemplateMap.add(
  "straight", // 直線連線
  $(go.Link, $(go.Shape))
);

myDiagram.linkTemplateMap.add(
  "curved", // 曲線連線
  $(go.Link, { curve: go.Link.Bezier }, $(go.Shape))
);
myDiagram.model.addLinkData({ from: 1, to: 2, category: "straight" });
myDiagram.model.addLinkData({ from: 3, to: 4, category: "curved" });

36.監聽在圖形物件 GraphObject 上的右鍵單擊

也就是獲取 右鍵點選的物件

myDiagram.addDiagramListener("ObjectContextClicked", function (e) {
  var linkOrNode = myDiagram.findPartAt(e.diagram.firstInput.documentPoint);
  if (linkOrNode instanceof go.Link) {
    //  TODO
  }
  if (linkOrNode instanceof go.Node) {
    //  TODO
  }
});

37.定義節點/連線/canvas 背景上的右鍵選單

可以結合 右鍵點選的物件,進行一些操作,對右鍵的物件,進行一些 contextMenu 中的操作

myDiagram = $(go.Diagram, "myDiagramDiv", {
  contextMenu: createContextMenu(),
});
myDiagram.nodeTemplate.contextMenu = createContextMenu();
myDiagram.linkTemplate.contextMenu = createContextMenu();

function groupContextMenu() {
  return $(
    "ContextMenu",
    "Vertical",
    $(
      "ContextMenuButton",
      $(
        go.Panel,
        "Horizontal",
        {
          alignment: go.Spot.Left,
        },
        $(go.Picture, "圖片src,如果不需要圖片可刪除", {
          desiredSize: new go.Size(60, 30),
          margin: new go.Margin(5, 5, 5, 10),
        }),
        $(go.TextBlock, "文字")
      ),
      {
        click: (event, obj) => {}, // 右鍵選單皮膚點選事件
      }
    )
  );
}

38.從節點動態拉出一根連線時,判斷其方向是左還是右?

可以透過判斷連線的起點和終點的位置來確定其方向。具體來說,可以透過比較起點和終點的 x 座標來判斷連線的方向,如果起點的 x 座標小於終點的 x 座標,則連線是從左向右的,反之則是從右向左的。

重寫了insertLink方法,當使用者在節點上開始拖動連線時,會呼叫該方法。在該方法中首先呼叫了go.LinkingTool.prototype.insertLink.call(this)來執行預設的連線操作,然後根據起點和終點的位置來設定連線的樣式。如果起點的 x 座標小於終點的 x 座標,則將連線的顏色設定為綠色,否則將其設定為紅色。

// 連線基本模板配置
myDiagram.linkTemplate = $(
  MessageLink,
  { selectionAdorned: true, curviness: 0 },
  $(go.Shape, "Rectangle", new go.Binding("stroke", "stroke").makeTwoWay()),
  $(
    go.Shape,
    { toArrow: "OpenTriangle" },
    new go.Binding("stroke", "stroke").makeTwoWay()
  )
);

// insertLink
go.LinkingTool.prototype.insertLink = function (
  fromnode,
  fromport,
  tonode,
  toport
) {
  var newlink = go.LinkingTool.prototype.insertLink.call(
    this,
    fromnode,
    fromport,
    tonode,
    toport
  );
  if (newlink !== null) {
    var model = this.diagram.model;
    if (fromnode.position.x < tonode.position.x) {
      model.setDataProperty(newlink.data, "stroke", "green"); // 從左向右的連線
    } else {
      model.setDataProperty(newlink.data, "stroke", "red"); // 從左向右的連線
    }
  }
  return newlink;
};

39.linkTemplate routing 取值

linkTemplate 是用於定義連線線的模板。而 routing 是用於定義連線線的路徑的屬性之一

如果沒有設定 routing 屬性,連線線的預設路徑是 go.Link.Normal。表示連線線會直接從起點到終點的位置。這種路徑適用於大多數情況,但在某些情況下可能需要更復雜的路徑。 以下值 :

  • go.Link.Normal:連線線會直接從起點到終點的位置。
  • go.Link.JumpOver:連線線會跳過節點,但可能會穿過其他連線線。
  • go.Link.AvoidsNodes:連線線會避開節點,但可能會穿過其他連線線。
  • go.Link.Orthogonal:連線線會沿著水平和垂直方向移動,直到到達目標節點的位置。

40.在移動連線時,改變所有點的位置

在 gojs 中,可以透過重寫go.DraggingTool.prototype.moveParts方法來實現移動時改變所有點的位置。具體實現步驟如下:

  1. 獲取被移動的部件的所有連線線(links)。
  2. 遍歷連線線,獲取連線線的路徑(path)。
  3. 遍歷路徑的所有點(points),將每個點的位置加上移動的距離(deltaX 和 deltaY)。
  4. 將修改後的點陣列設定迴路徑的part.points屬性中。
MessageDraggingTool.prototype.moveParts = function (parts, offset, check) {
  go.DraggingTool.prototype.moveParts.call(this, parts, offset, check);
  var it = parts.iterator;

  while (it.next()) {
    if (it.key instanceof go.Link) {
      var link = it.key;
      var path = link.path;
      var points = path.part.points;

      if (points.length == 3) {
        // 表示直線
        var startX = it.value.point.x;
        var startY = it.value.point.y;
        var x = startX + offset.x;
        var y = startY + offset.y;
        link.diagram.model.set(link.data, "表示連線定位的欄位x", "當前位置x");
        link.diagram.model.set(link.data, "表示連線定位的欄位y", "當前位置y");
      } else {
        // 表示曲線
        var pointArray: any = [];
        for (var i = 0; i < points.length; i++) {
          var point = points._dataArray[i];
          pointArray.push(new go.Point(point.x + offset.x, point.y + offset.y));
        }
        path.part.points = pointArray;
      }
    }
  }
};

相關文章