Можно ли сделать группы непересекающимися в GoJS? - PullRequest
0 голосов
/ 22 мая 2019

У меня есть несколько групп с узлами, и я хотел бы, чтобы эти группы не пересекались при движении.Что мне нужно для этого сделать?Вот пример шаблона моей группы.

$(go.Group, "Auto",
  {
    layout: $(go.LayeredDigraphLayout, {
      direction: 0,
      columnSpacing: 10,
      initializeOption: go.LayeredDigraphLayout.InitDepthFirstOut,
      aggressiveOption: go.LayeredDigraphLayout.AggressiveMore
    }),
    minSize: new go.Size(800, 30),
    computesBoundsIncludingLocation: true,
    computesBoundsIncludingLinks: true,
    computesBoundsAfterDrag: true,
    isSubGraphExpanded: true
  },
  $(go.Shape, "Rectangle", [
    {
      fill: null,
      stroke: "gray",
      strokeWidth: 2
    },
    new go.Binding('fill', '', function (group) {
      return group.data.isEditable ? '#eee' : '#F7EAEC';
    }).ofObject('')
  ]),
  $(go.Panel, "Vertical",
    { defaultAlignment: go.Spot.Left },
    $(go.Panel, "Horizontal",
      { defaultAlignment: go.Spot.Top },
      $(go.TextBlock,
        { font: "Bold 18px Sans-Serif", textAlign: "left" },
        new go.Binding("text", "name"))
      ),
      $(go.Placeholder,
        { padding: new go.Margin(10, 10), margin: 0 })
      )
    );

1 Ответ

1 голос
/ 23 мая 2019

Оптимизация, которая необходима, заключается в том, чтобы рассматривать группы как атомарные объекты.Нет необходимости проверять, перекрывают ли какие-либо узлы-члены группы какие-либо узлы, когда один уже проверил всю группу.

Реализация, которая заключается в добавлении двух строк к функции navig в этом примере., https://gojs.net/latest/samples/dragUnoccupied.html.

  function isUnoccupied(r, node) {
    var diagram = node.diagram;

    // nested function used by Layer.findObjectsIn, below
    // only consider Parts, and ignore the given Node and any Links
    function navig(obj) {
      var part = obj.part;
      if (part === node) return null;
      if (part instanceof go.Link) return null;

      // add these two checks:
      if (part.isMemberOf(node)) return null;
      if (node.isMemberOf(part)) return null;

      return part;
    }

    // only consider non-temporary Layers
    var lit = diagram.layers;
    while (lit.next()) {
      var lay = lit.value;
      if (lay.isTemporary) continue;
      if (lay.findObjectsIn(r, navig, null, true).count > 0) return false;
    }
    return true;
  }

  // a Part.dragComputation function that prevents a Part from being dragged to overlap another Part
  function avoidNodeOverlap(node, pt, gridpt) {
    if (node.diagram instanceof go.Palette) return gridpt;
    // this assumes each node is fully rectangular
    var bnds = node.actualBounds;
    var loc = node.location;
    // use PT instead of GRIDPT if you want to ignore any grid snapping behavior
    // see if the area at the proposed location is unoccupied
    var r = new go.Rect(gridpt.x - (loc.x - bnds.x), gridpt.y - (loc.y - bnds.y), bnds.width, bnds.height);
    // maybe inflate R if you want some space between the node and any other nodes
    r.inflate(-0.5, -0.5);  // by default, deflate to avoid edge overlaps with "exact" fits
    // when dragging a node from another Diagram, choose an unoccupied area
    if (!(node.diagram.currentTool instanceof go.DraggingTool) &&
        (!node._temp || !node.layer.isTemporary)) {  // in Temporary Layer during external drag-and-drop
      node._temp = true;  // flag to avoid repeated searches during external drag-and-drop
      while (!isUnoccupied(r, node)) {
        r.x += 10;  // note that this is an unimaginative search algorithm --
        r.y += 10;  // you can improve the search here to be more appropriate for your app
      }
      r.inflate(0.5, 0.5);  // restore to actual size
      // return the proposed new location point
      return new go.Point(r.x - (loc.x - bnds.x), r.y - (loc.y - bnds.y));
    }
    if (isUnoccupied(r, node)) return gridpt;  // OK
    return loc;  // give up -- don't allow the node to be moved to the new location
  }

  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          {
            "undoManager.isEnabled": true,
            // support creating groups with Ctrl-G
            "commandHandler.archetypeGroupData": { isGroup: true, text: "NEW GROUP" }
          });

    myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        { // avoid overlapping other nodes
          dragComputation: avoidNodeOverlap
        },
        $(go.Shape,
          { fill: "white", portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer" },
          new go.Binding("fill", "color")),
        $(go.TextBlock,
          { margin: 8, editable: true },
          new go.Binding("text").makeTwoWay())
      );

    myDiagram.groupTemplate =
      $(go.Group, "Vertical",
        { // avoid overlapping other nodes
          dragComputation: avoidNodeOverlap,
          // support ungrouping by Ctrl-Shift-G
          ungroupable: true
        },
        $(go.TextBlock,
          { font: "bold 14pt sans-serif", editable: true },
          new go.Binding("text").makeTwoWay()),
        $(go.Panel, "Auto",
          $(go.Shape, { fill: "lightgray" }),
          $(go.Placeholder, { padding: 5 })
        )
      );

    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 1, text: "Alpha", color: "lightblue" },
      { key: 2, text: "Beta", color: "orange" },
      { key: 3, text: "Gamma", color: "lightgreen" },
      { key: 4, text: "Delta", color: "pink" }
    ],
    [
      { from: 1, to: 2 },
      { from: 1, to: 3 },
      { from: 2, to: 2 },
      { from: 3, to: 4 },
      { from: 4, to: 1 }
    ]);
  }

Чтобы создать группу, выберите несколько узлов и введите Control-G.

...