gojs
Version:
Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams
179 lines (169 loc) • 8.99 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="A diagram that does not scroll or zoom and has a fixed area in which to move parts."/>
<link rel="stylesheet" href="../assets/css/style.css"/>
<!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
<title>Absolute positioning within the viewport</title>
</head>
<body>
<!-- This top nav is not part of the sample code -->
<nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
<div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
<div class="md:pl-4">
<a class="text-white hover:text-white no-underline hover:no-underline
font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
<h1 class="my-0 p-1 ">GoJS</h1>
</a>
</div>
<button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
<svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
<path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
<path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button>
<div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
<ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
<li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
<li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
</ul>
</div>
</div>
<hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
</nav>
<div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
<div id="navSide" class="flex flex-col w-full md:w-48 text-gray-700 bg-white flex-shrink-0"></div>
<!-- * * * * * * * * * * * * * -->
<!-- Start of GoJS sample code -->
<script src="../release/go.js"></script>
<div id="allSampleContent" class="p-4 w-full">
<script id="code">
function init() {
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
// Since 2.2 you can also author concise templates with method chaining instead of GraphObject.make
// For details, see https://gojs.net/latest/intro/buildingObjects.html
const $ = go.GraphObject.make;
myDiagram =
new go.Diagram("myDiagramDiv",
{
fixedBounds: new go.Rect(0, 0, 500, 300), // document is always 500x300 units
allowHorizontalScroll: false, // disallow scrolling or panning
allowVerticalScroll: false,
allowZoom: false, // disallow zooming
"animationManager.isEnabled": false,
"undoManager.isEnabled": true,
"ModelChanged": e => { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
document.getElementById("mySavedModel").textContent = e.model.toJson();
}
}
});
// the background Part showing the fixed bounds of the diagram contents
myDiagram.add(
$(go.Part,
{ layerName: "Grid", position: myDiagram.fixedBounds.position },
$(go.Shape, { fill: "oldlace", strokeWidth: 0, desiredSize: myDiagram.fixedBounds.size })
));
// This function is the Node.dragComputation, to limit the movement of the parts.
function stayInFixedArea(part, pt, gridpt) {
var diagram = part.diagram;
if (diagram === null) return pt;
// compute the document area without padding
var v = diagram.documentBounds.copy().subtractMargin(diagram.padding);
// get the bounds of the part being dragged
var bnd = part.actualBounds;
var loc = part.location;
// now limit the location appropriately
var l = v.x + (loc.x - bnd.x);
var r = v.right - (bnd.right - loc.x);
var t = v.y + (loc.y - bnd.y);
var b = v.bottom - (bnd.bottom - loc.y);
if (l <= gridpt.x && gridpt.x <= r && t <= gridpt.y && gridpt.y <= b) return gridpt;
var p = gridpt.copy();
if (diagram.toolManager.draggingTool.isGridSnapEnabled) {
// find a location that is inside V but also keeps the part's bounds within V
var cw = diagram.grid.gridCellSize.width;
if (cw > 0) {
while (p.x > r) p.x -= cw;
while (p.x < l) p.x += cw;
}
var ch = diagram.grid.gridCellSize.height;
if (ch > 0) {
while (p.y > b) p.y -= ch;
while (p.y < t) p.y += ch;
}
return p;
} else {
p.x = Math.max(l, Math.min(p.x, r));
p.y = Math.max(t, Math.min(p.y, b));
return p;
}
}
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{ dragComputation: stayInFixedArea },
// get the size from the model data
new go.Binding("desiredSize", "size", go.Size.parse),
// get and set the position in the model data
new go.Binding("position", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
// temporarily put selected nodes in Foreground layer
new go.Binding("layerName", "isSelected", s => s ? "Foreground" : "").ofObject(),
$(go.Shape, "Rectangle",
{ strokeWidth: 0 }, // avoid extra thickness from the stroke
new go.Binding("fill", "color")),
$(go.TextBlock,
new go.Binding("text", "color"))
);
myDiagram.model = new go.GraphLinksModel([
{ "key": "Alpha", "pos": "0 0", "size": "50 50", "color": "lightblue" },
{ "key": "Beta", "pos": "276 19", "size": "100 100", "color": "orange" },
{ "key": "Gamma", "pos": "44 214", "size": "100 50", "color": "lightgreen" },
{ "key": "Delta", "pos": "239 171", "size": "50 100", "color": "pink" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Alpha", to: "Gamma" },
{ from: "Gamma", to: "Delta" },
{ from: "Delta", to: "Alpha" }
]);
}
window.addEventListener('DOMContentLoaded', init);
</script>
<div id="sample">
<div id="myDiagramDiv" style="width:100%; height:400px"></div>
<p>
Absolute positioning within the viewport, with no scrolling (or panning) or zooming allowed.
</p>
<p>
There is a special colored background Part that shows the fixed area where Parts may be.
It is in the "Grid" Layer so that it is not selectable and is always behind the regular Parts.
</p>
<p>
Parts may not be dragged outside of the fixed document area of the diagram.
This is implemented by a custom <a>Part.dragComputation</a> function.
</p>
<p>
Note that the user may still scroll or zoom the whole page.
</p>
<p>The model data, automatically updated after each change or undo or redo:</p>
<textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
</div>
</div>
<!-- * * * * * * * * * * * * * -->
<!-- End of GoJS sample code -->
</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>