是否可以使组在 GoJS 中不相交?
Is it possible to make groups non-intersecting in GoJS?
我有几个节点组,我想让这些组在移动时不相交。我需要为此做什么?有一个我的组模板的例子。
$(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 })
)
);
需要的优化是将组视为原子对象。当已经检查了整个组时,无需测试组的任何成员节点是否也与任何节点重叠。
实施只需向该示例中的 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 }
]);
}
要创建一个组,select 一些节点并键入 Control-G。
在您的节点模板中设置:
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{ dragComputation: avoidNodeOverlap });
您可以在此处查看解决方案:
https://gojs.net/latest/samples/dragUnoccupied.html
我有几个节点组,我想让这些组在移动时不相交。我需要为此做什么?有一个我的组模板的例子。
$(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 })
)
);
需要的优化是将组视为原子对象。当已经检查了整个组时,无需测试组的任何成员节点是否也与任何节点重叠。
实施只需向该示例中的 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 }
]);
}
要创建一个组,select 一些节点并键入 Control-G。
在您的节点模板中设置:
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{ dragComputation: avoidNodeOverlap });
您可以在此处查看解决方案: https://gojs.net/latest/samples/dragUnoccupied.html