create-gojs-kit
Version:
A CLI for downloading GoJS samples, extensions, and docs
310 lines (273 loc) • 13.8 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
<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 itemprop="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 property="og: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="twitter:description" content="In one diagram show the whole tree and in a second diagram show a subset that is logically near a selected node." />
<link rel="preconnect" href="https://rsms.me/">
<link rel="stylesheet" href="../assets/css/style.css">
<!-- Copyright 1998-2025 by Northwoods Software Corporation. -->
<meta itemprop="name" content="Full Diagram and its Local View" />
<meta property="og:title" content="Full Diagram and its Local View" />
<meta name="twitter:title" content="Full Diagram and its Local View" />
<meta property="og:image" content="https://gojs.net/latest/assets/images/screenshots/localview.png" />
<meta itemprop="image" content="https://gojs.net/latest/assets/images/screenshots/localview.png" />
<meta name="twitter:image" content="https://gojs.net/latest/assets/images/screenshots/localview.png" />
<meta property="og:url" content="https://gojs.net/latest/samples/localView.html" />
<meta property="twitter:url" content="https://gojs.net/latest/samples/localView.html" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="og:type" content="website" />
<meta property="twitter:domain" content="gojs.net" />
<title>
Full Diagram and its Local View | GoJS Diagramming Library
</title>
</head>
<body>
<!-- This top nav is not part of the sample code -->
<nav id="navTop" class=" w-full h-[var(--topnav-h)] z-30 bg-white border-b border-b-gray-200">
<div class="max-w-screen-xl mx-auto flex flex-wrap items-start justify-between px-4">
<a class="text-white bg-nwoods-primary font-bold !leading-[calc(var(--topnav-h)_-_1px)] my-0 px-2 text-4xl lg:text-5xl logo"
href="../">
GoJS
</a>
<div class="relative">
<button id="topnavButton" class="h-[calc(var(--topnav-h)_-_1px)] px-2 m-0 text-gray-900 bg-inherit shadow-none md:hidden hover:!bg-inherit hover:!text-nwoods-accent hover:!shadow-none" aria-label="Navigation">
<svg class="h-7 w-7 block" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<div id="topnavList" class="hidden md:block">
<div class="absolute right-0 z-30 flex flex-col items-end rounded border border-gray-200 p-4 pl-12 shadow bg-white text-gray-900 font-semibold
md:flex-row md:space-x-4 md:items-start md:border-0 md:p-0 md:shadow-none md:bg-inherit">
<a href="../learn/">Learn</a>
<a href="../samples/">Samples</a>
<a href="../intro/">Intro</a>
<a href="../api/">API</a>
<a href="../download.html">Download</a>
<a href="https://forum.nwoods.com/c/gojs/11" target="_blank" rel="noopener">Forum</a>
<a id="tc" href="https://nwoods.com/contact.html"
target="_blank" rel="noopener" onclick="getOutboundLink('https://nwoods.com/contact.html', 'contact');">Contact</a>
<a id="tb" href="https://nwoods.com/sales/index.html"
target="_blank" rel="noopener" onclick="getOutboundLink('https://nwoods.com/sales/index.html', 'buy');">Buy</a>
</div>
</div>
</div>
</div>
</nav>
<script>
window.addEventListener("DOMContentLoaded", function () {
// topnav
var topButton = document.getElementById("topnavButton");
var topnavList = document.getElementById("topnavList");
if (topButton && topnavList) {
topButton.addEventListener("click", function (e) {
topnavList
.classList
.toggle("hidden");
e.stopPropagation();
});
document.addEventListener("click", function (e) {
// if the clicked element isn't the list, close the list
if (!topnavList.classList.contains("hidden") && !e.target.closest("#topnavList")) {
topButton.click();
}
});
// set active <a> element
var url = window
.location
.href
.toLowerCase();
var aTags = topnavList.getElementsByTagName('a');
for (var i = 0; i < aTags.length; i++) {
var lowerhref = aTags[i]
.href
.toLowerCase();
if (lowerhref.endsWith('.html'))
lowerhref = lowerhref.slice(0, -5);
if (url.startsWith(lowerhref)) {
aTags[i]
.classList
.add('active');
break;
}
}
}
});
</script>
<div class="flex flex-col prose">
<div class="w-full max-w-screen-xl mx-auto">
<!-- * * * * * * * * * * * * * -->
<!-- Start of GoJS sample code -->
<script src="https://cdn.jsdelivr.net/npm/gojs@3.1.0"></script>
<div id="allSampleContent" class="p-4 w-full">
<script id="code">
function init() {
myFullDiagram = new go.Diagram('fullDiagram', {
initialAutoScale: go.AutoScale.Uniform, // automatically scale down to show whole tree
contentAlignment: go.Spot.Center, // center the tree in the viewport if it fits
isReadOnly: true, // don't allow user to change the diagram
'animationManager.isEnabled': false,
layout: new go.TreeLayout({ angle: 90, sorting: go.TreeSorting.Ascending }),
maxSelectionCount: 1, // only one node may be selected at a time in each diagram
// when the selection changes, update the myLocalDiagram view
ChangedSelection: showLocalOnFullClick
});
// this is very similar to the full Diagram
myLocalDiagram = new go.Diagram('localDiagram', {
initialAutoScale: go.AutoScale.UniformToFill,
contentAlignment: go.Spot.Center,
isReadOnly: true,
'animationManager.isInitial': false,
layout: new go.TreeLayout({ angle: 90, sorting: go.TreeSorting.Ascending }),
LayoutCompleted: 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 =
new go.Node('Auto', { locationSpot: go.Spot.Center })
.bind('text', 'key', go.Binding.toString) // for sorting
.add(
new go.Shape('Rectangle', { stroke: null })
.bind('fill', 'color'),
new go.TextBlock({ margin: 5 })
.bind('text', 'key', k => 'node' + k)
);
myFullDiagram.nodeTemplate = myNodeTemplate;
myLocalDiagram.nodeTemplate = myNodeTemplate;
// Define a basic link template, not selectable, shared by both diagrams
var myLinkTemplate =
new go.Link({ corner: 10, selectable: false })
.add(
new 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 =
new go.Part('Auto', { layerName: 'Grid', locationSpot: go.Spot.Center })
.add(
new go.Shape('Ellipse', {
fill: new go.Brush('Radial', { 0.0: 'gold', 0.5: 'gold', 1.0: 'white' }),
stroke: null,
desiredSize: new go.Size(300, 300)
})
);
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', 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 gold part 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(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);
}
window.addEventListener('DOMContentLoaded', init);
</script>
<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 gold 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>
</div>
<!-- * * * * * * * * * * * * * -->
<!-- End of GoJS sample code -->
</div>
<div id="allTagDescriptions" class="p-4 w-full max-w-screen-xl mx-auto">
<hr/>
<h3 class="text-xl">GoJS Features in this sample</h3>
<!-- blacklist tags that do not correspond to a specific GoJS feature -->
<h4>Tree Layout</h4>
<p>
This predefined layout is used for placing Nodes of a tree-structured graph in layers (rows or columns).
For discussion and examples of the most commonly used properties of the <a href="../api/symbols/TreeLayout.html">TreeLayout</a>,
see the <a href="../intro/trees.html">Trees</a> page in the Introduction.
More information can be found in the <a href="../intro/layouts.html#TreeLayout">GoJS Intro</a>.
</p>
<p>
<a href="../samples/index.html#treelayout">Related samples</a>
</p>
<hr>
</div>
</div>
</body>
<!-- This script is part of the gojs.net website, and is not needed to run the sample -->
<script src="../assets/js/goSamples.js"></script>
</html>