Hi,
The following diagram is using the SwimLaneLayout with the given nodeDataArray and linkDataArray below
const nodeDataArray = [
{
key: "A",
isGroup: true,
},
{
key: "Box1",
group: "A",
},
{
key: "Box2",
group: "A",
},
{
key: "Box3",
group: "A",
},
{
key: "Box4",
group: "A",
},
{
key: "Box5",
group: "A",
},
];
const linkDataArray = [
{
from: "Box1",
to: "Box2",
},
{
from: "Box2",
to: "Box5",
},
{
from: "Box1",
to: "Box3",
},
{
from: "Box3",
to: "Box4",
},
{
from: "Box4",
to: "Box5",
},
];
I realized that there is a “dummy” vertex with node as null in the same layer as Box3.
My first question is why the default layout calculation put Box3 above the dummy vertex, which causes an unnecessary link crossing (box1-box2 with box3-box4). If the dummy vertex is above Box3, there will be no link crossing.
My second question is if we could override the default calculation.
My third question is if we could manually adjust it by dragging the dummy vertex above Box3, as shown below.
I looked at the event.subject (as the reshaped link) in the LinkReshaped event handler. But I have no clue how to put the dummy vertex above Box3. Any example code would be really appreciated!
I am pasting my HTML + JS code below as usual. Thanks so much for your time!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div
id="myDiagramDiv"
style="border: solid 1px black; width: 100%; height: 700px"
></div>
<script src="../../release/go-debug.js"></script>
<script src="../../extensions/SwimLaneLayout.js"></script>
<script>
let myDiagram;
function init() {
const $ = go.GraphObject.make;
myDiagram = $(go.Diagram, "myDiagramDiv", {
layout: $(SwimLaneLayout, {
laneProperty: "group",
layerSpacing: 20,
commitLayers: function (layerRects, offset) {
if (layerRects.length === 0) return;
var horiz = true;
var forwards = true;
var rect = layerRects[forwards ? layerRects.length - 1 : 0];
var totallength = horiz ? rect.right : rect.bottom;
for (var i = 0; i < this.laneNames.length; i++) {
var lane = this.laneNames[i];
// assume lane names do not conflict with node names
var group = this.diagram.findNodeForKey(lane);
if (group === null) {
this.diagram.model.addNodeData({ key: lane, isGroup: true });
group = this.diagram.findNodeForKey(lane);
}
if (horiz) {
group.location = new go.Point(
-this.layerSpacing / 2,
this.lanePositions.get(lane) * this.columnSpacing +
offset.y,
);
} else {
group.location = new go.Point(
this.lanePositions.get(lane) * this.columnSpacing +
offset.x,
-this.layerSpacing / 2,
);
}
var ph = group.findObject("PLACEHOLDER"); // won't be a go.Placeholder, but just a regular Shape
if (ph === null) ph = group;
if (horiz) {
ph.desiredSize = new go.Size(
totallength,
this.laneBreadths.get(lane) * this.columnSpacing,
);
} else {
ph.desiredSize = new go.Size(
this.laneBreadths.get(lane) * this.columnSpacing,
totallength,
);
}
}
},
}),
});
myDiagram.nodeTemplate = $(
go.Node,
"Spot",
new go.Binding("location", "loc", go.Point.parse),
$(go.Shape, "RoundedRectangle", {
fill: "white",
width: 100,
height: 50,
portId: "",
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
}),
$(
go.TextBlock, // the text label
new go.Binding("text", "key"),
{
verticalAlignment: go.Spot.Center,
textAlign: "center",
},
),
);
myDiagram.linkTemplate = $(
go.Link,
{
curve: go.Link.Bezier,
toShortLength: 8,
fromEndSegmentLength: 50,
toEndSegmentLength: 50,
reshapable: true,
},
$(go.Shape, { isPanelMain: true, strokeWidth: 2 }),
$(go.Shape, { toArrow: "Standard", stroke: null }),
);
myDiagram.groupTemplate = $(
go.Group,
"Horizontal",
{
layerName: "Background",
movable: false,
copyable: false,
locationObjectName: "PLACEHOLDER",
layout: null,
avoidable: false,
},
$(
go.TextBlock,
{
font: "bold 12pt sans-serif",
angle: 270,
},
new go.Binding("text", "key"),
),
$(
go.Panel,
"Auto",
$(go.Shape, { fill: "transparent", stroke: "orange" }),
$(go.Shape, {
name: "PLACEHOLDER",
fill: null,
stroke: null,
strokeWidth: 0,
}),
),
);
const nodeDataArray = [
{
key: "A",
isGroup: true,
},
{
key: "Box1",
group: "A",
},
{
key: "Box2",
group: "A",
},
{
key: "Box3",
group: "A",
},
{
key: "Box4",
group: "A",
},
{
key: "Box5",
group: "A",
},
];
const linkDataArray = [
{
from: "Box1",
to: "Box2",
},
{
from: "Box2",
to: "Box5",
},
{
from: "Box1",
to: "Box3",
},
{
from: "Box3",
to: "Box4",
},
{
from: "Box4",
to: "Box5",
},
];
const model = new go.GraphLinksModel();
model.nodeDataArray = nodeDataArray;
model.linkDataArray = linkDataArray;
myDiagram.model = model;
myDiagram.addDiagramListener("LinkReshaped", (event) => {
console.log(event.subject.data);
});
}
window.addEventListener("DOMContentLoaded", init);
</script>
</body>
</html>