Oops – actually, setting TreeLayout.alignment only aligns the children of that node, not all nodes for the whole diagram regardless of parent.
Other than that discrepancy, try this code:
function init() {
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
var $ = go.GraphObject.make; // for conciseness in defining templates
myDiagram =
$(go.Diagram, "myDiagram",
{
contentAlignment: go.Spot.Center, // center the tree in the viewport
isReadOnly: true, // don't allow user to change the diagram
"animationManager.isEnabled": false,
maxSelectionCount: 1, // only one node may be selected at a time in each diagram
// when the selection changes, highlight the path to the root and collapse all nodes away from path
"ChangedSelection": function(e) {
highlightPath(e.diagram.selection.first());
}
});
// Define a node template that is shared by both diagrams
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{ locationSpot: go.Spot.Center },
new go.Binding("text", "key", go.Binding.toString), // for sorting
$(go.Shape, "RoundedRectangle",
new go.Binding("fill", "color"),
{ stroke: "gray", strokeWidth: 2 },
new go.Binding("stroke", "isHighlighted", function(h) { return h ? "red" : "gray"; }).ofObject()),
$(go.TextBlock,
{ margin: 1 },
new go.Binding("text", "key", function(k) { return "node" + k; }))
);
// Define a basic link template, not selectable, shared by both diagrams
myDiagram.linkTemplate =
$(go.Link,
{ routing: go.Link.Normal, selectable: false, layerName: "Background" },
$(go.Shape,
{ strokeWidth: 1 })
);
// Create the full tree diagram
setupDiagram();
layout();
}
// Create the tree model containing TOTAL nodes, with each node having a variable number of children
function setupDiagram(total) {
if (total === undefined) total = 100; // default to 100 nodes
var nodeDataArray = [];
for (var i = 0; i < total; i++) {
nodeDataArray.push({
key: nodeDataArray.length,
color: go.Brush.randomColor()
});
}
var j = 0;
for (var i = 1; i < total; i++) {
var data = nodeDataArray[i];
data.parent = j;
if (Math.random() < 0.3) j++; // this controls the likelihood that there are enough children
}
myDiagram.model = new go.TreeModel(nodeDataArray);
}
function layout() {
var radio = document.getElementsByName("view");
var view = "Tree";
for (var i = 0; i < radio.length; i++) {
if (radio[i].checked) view = radio[i].value;
}
var linklayer = myDiagram.findLayer("Background");
if (view === "Stack") {
myDiagram.layout = go.GraphObject.make(go.TreeLayout,
{
angle: 90, sorting: go.TreeLayout.SortingAscending,
layerSpacing: 10, alignment: go.TreeLayout.AlignmentStart
});
linklayer.opacity = 0;
} else { // "Tree"
myDiagram.layout = go.GraphObject.make(go.TreeLayout,
{
angle: 90, sorting: go.TreeLayout.SortingAscending
});
linklayer.opacity = 1;
}
}
function highlightPath(node) {
if (node === null) return;
myDiagram.startTransaction("highlight");
node.findTreeRoot().collapseTree();
myDiagram.nodes.each(function(n) { n.wasTreeExpanded = false; });
myDiagram.clearHighlighteds();
var n = node;
while (n !== null) {
n.isHighlighted = true;
n.expandTree(1);
n = n.findTreeParentNode();
}
myDiagram.commitTransaction("highlight");
}
The HTML:
<div id="myDiagram" style="height:500px;width:100%;border:1px solid black;margin:2px"></div>
<input type="radio" name="view" onclick="layout()" value="Tree" checked="checked" />Tree View
<input type="radio" name="view" onclick="layout()" value="Stack" />Stack View