gojs
Version:
Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams
187 lines (176 loc) • 8.31 kB
HTML
<html>
<head>
<meta charset="UTF-8">
<title>Local View</title>
<meta name="description" content="In one diagram show the whole tree and in a second diagram show a subset that is logically near a selected node." />
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
<script src="../release/go.js"></script>
<script src="../assets/js/goSamples.js"></script> <!-- this is only for the GoJS Samples framework -->
<script id="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
myFullDiagram =
$(go.Diagram, "fullDiagram", // each diagram refers to its DIV HTML element by id
{
initialAutoScale: go.Diagram.UniformToFill, // automatically scale down to show whole tree
maxScale: 0.25,
contentAlignment: go.Spot.Center, // center the tree in the viewport
isReadOnly: true, // don't allow user to change the diagram
"animationManager.isEnabled": false,
layout: $(go.TreeLayout,
{ angle: 90, sorting: go.TreeLayout.SortingAscending }),
maxSelectionCount: 1, // only one node may be selected at a time in each diagram
// when the selection changes, update the myLocalDiagram view
"ChangedSelection": showLocalOnFullClick
});
myLocalDiagram = // this is very similar to the full Diagram
$(go.Diagram, "localDiagram",
{
autoScale: go.Diagram.UniformToFill,
contentAlignment: go.Spot.Center,
isReadOnly: true,
layout: $(go.TreeLayout,
{ angle: 90, sorting: go.TreeLayout.SortingAscending }),
"LayoutCompleted": function(e) {
var sel = e.diagram.selection.first();
if (sel !== null) myLocalDiagram.scrollToRect(sel.actualBounds);
},
maxSelectionCount: 1,
// when the selection changes, update the contents of the myLocalDiagram
"ChangedSelection": showLocalOnLocalClick
});
// Define a node template that is shared by both diagrams
var myNodeTemplate =
$(go.Node, "Auto",
{ locationSpot: go.Spot.Center },
new go.Binding("text", "key", go.Binding.toString), // for sorting
$(go.Shape, "Rectangle",
new go.Binding("fill", "color"),
{ stroke: null }),
$(go.TextBlock,
{ margin: 5 },
new go.Binding("text", "key", function(k) { return "node" + k; }))
);
myFullDiagram.nodeTemplate = myNodeTemplate;
myLocalDiagram.nodeTemplate = myNodeTemplate;
// Define a basic link template, not selectable, shared by both diagrams
var myLinkTemplate =
$(go.Link,
{ routing: go.Link.Normal, selectable: false },
$(go.Shape,
{ strokeWidth: 1 })
);
myFullDiagram.linkTemplate = myLinkTemplate;
myLocalDiagram.linkTemplate = myLinkTemplate;
// Create the full tree diagram
setupDiagram();
// Create a part in the background of the full diagram to highlight the selected node
highlighter =
$(go.Part, "Auto",
{
layerName: "Background",
selectable: false,
isInDocumentBounds: false,
locationSpot: go.Spot.Center
},
$(go.Shape, "Ellipse",
{
fill: $(go.Brush, "Radial", { 0.0: "yellow", 1.0: "white" }),
stroke: null,
desiredSize: new go.Size(400, 400)
})
);
myFullDiagram.add(highlighter);
// Start by focusing the diagrams on the node at the top of the tree.
// Wait until the tree has been laid out before selecting the root node.
myFullDiagram.addDiagramListener("InitialLayoutCompleted", function(e) {
var node0 = myFullDiagram.findPartForKey(0);
if (node0 !== null) node0.isSelected = true;
showLocalOnFullClick();
});
}
// Make the corresponding node in the full diagram to that selected in the local diagram selected,
// then call showLocalOnFullClick to update the local diagram.
function showLocalOnLocalClick() {
var selectedLocal = myLocalDiagram.selection.first();
if (selectedLocal !== null) {
// there are two separate Nodes, one for each Diagram, but they share the same key value
myFullDiagram.select(myFullDiagram.findPartForKey(selectedLocal.data.key));
}
}
function showLocalOnFullClick() {
var node = myFullDiagram.selection.first();
if (node !== null) {
// make sure the selected node is in the viewport
myFullDiagram.scrollToRect(node.actualBounds);
// move the large yellow node behind the selected node to highlight it
highlighter.location = node.location;
// create a new model for the local Diagram
var model = new go.TreeModel();
// add the selected node and its children and grandchildren to the local diagram
var nearby = node.findTreeParts(3); // three levels of the (sub)tree
// add parent and grandparent
var parent = node.findTreeParentNode();
if (parent !== null) {
nearby.add(parent);
var grandparent = parent.findTreeParentNode();
if (grandparent !== null) {
nearby.add(grandparent);
}
}
// create the model using the same node data as in myFullDiagram's model
nearby.each(function(n) {
if (n instanceof go.Node) model.addNodeData(n.data);
});
myLocalDiagram.model = model;
// select the node at the diagram's focus
var selectedLocal = myLocalDiagram.findPartForKey(node.data.key);
if (selectedLocal !== null) selectedLocal.isSelected = true;
}
}
// 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
}
myFullDiagram.model = new go.TreeModel(nodeDataArray);
}
</script>
</head>
<body onload="init()">
<div id="sample">
<div id="fullDiagram" style="height:250px;width:100%;border:1px solid black;margin:2px"></div>
<div id="localDiagram" style="height:350px;width:100%;border:1px solid black;margin:2px"></div>
<button onclick="setupDiagram()">Create New Tree</button>
<p>
This sample includes two diagrams, the one on top showing a full tree and the one below
focusing on a specific node in the tree and those nodes that are logically "near" it.
When the selection changes in either diagram, the lower diagram changes its focus to the selected node.
To show which node in the full tree is selected,
a large yellow highlighter part employing a radial <a>Brush</a> is placed in the background layer of the upper diagram behind the selected node.
The Create New Tree button will randomly generate a new <a>TreeModel</a> to be used by the diagrams.
</p>
<p>
Although it is not demonstrated in this sample,
one could well use very simple templates for Nodes and for Links in the top Diagram.
This would make the top Diagram more efficient to construct when there are very many more nodes.
And one could use more detailed templates in the bottom Diagram,
where there is more room to show information for each node.
</p>
</div>
</body>
</html>